深入了解 LINQ:关联数据查询实例讲解

4f962b84e72297b99ccea1e46539af25.png

概述:现在重点介绍利用 LINQ 查询数据库,特别是在处理各种模型关系(如一对一、一对多和多对多)时。本高级指南旨在填补资源缺口,并为您提供掌握这些概念的实用见解和代码示例。1. 了解数据库中的模型关系在深入研究 LINQ 查询之前,请务必了解数据库模型中的关系类型:一对一:表中的一条记录链接到另一个表中的一条记录,并且只有一条记录链 接。一对多:一个表中的记录可以与另一个表中的一个或多个记录相关联。多对多:一个表中的记录可以与另一个表中的多个记录相关联,反之亦然。为了说明 C# 中的各种关系,我们需要创建几个类来表示这些关系中涉及的实体。让我们为 、 、 、 、 、 和 中间类创建类,以演示一对一

现在重点介绍利用 LINQ 查询数据库,特别是在处理各种模型关系(如一对一、一对多和多对多)时。本高级指南旨在填补资源缺口,并为您提供掌握这些概念的实用见解和代码示例。

1. 了解数据库中的模型关系

在深入研究 LINQ 查询之前,请务必了解数据库模型中的关系类型:

一对一:表中的一条记录链接到另一个表中的一条记录,并且只有一条记录链> 接。 一对多:一个表中的记录可以与另一个表中的一个或多个记录相关联。 多对多:一个表中的记录可以与另一个表中的多个记录相关联,反之亦然。

为了说明 C# 中的各种关系,我们需要创建几个类来表示这些关系中涉及的实体。让我们为 、 、 、 、 、 和 中间类创建类,以演示一对一、一对多和多对多的关系。UserUserProfileCustomerOrderStudentCourseStudentCourse

一对一关系:用户和 UserProfile

public class User  
{  
    public int ID { get; set; }  
    public string Name { get; set; }  
    public UserProfile UserProfile { get; set; } // Navigation property for one-to-one relationship  
}  
  
public class UserProfile  
{  
    public int UserID { get; set; } // Primary key and also foreign key  
    public string ProfilePicture { get; set; }  
    public User User { get; set; } // Navigation property for one-to-one relationship  
}

一对多关系:客户和订单

public class Customer  
{  
    public int ID { get; set; }  
    public string Name { get; set; }  
    public List<Order> Orders { get; set; } // Navigation property for one-to-many relationship  
}  
  
public class Order  
{  
    public int OrderID { get; set; }  
    public int CustomerID { get; set; } // Foreign key  
    public decimal TotalAmount { get; set; }  
    public Customer Customer { get; set; } // Navigation property for one-to-many relationship  
}

多对多关系:学生、课程和 StudentCourse

public class Student  
{  
    public int ID { get; set; }  
    public string Name { get; set; }  
    public List<StudentCourse> StudentCourses { get; set; } // Navigation property for many-to-many relationship  
}  
  
public class Course  
{  
    public int ID { get; set; }  
    public string CourseName { get; set; }  
    public List<StudentCourse> StudentCourses { get; set; } // Navigation property for many-to-many relationship  
}  
  
public class StudentCourse  
{  
    public int StudentID { get; set; } // Composite key (StudentID, CourseID)  
    public int CourseID { get; set; }  // Composite key (StudentID, CourseID)  
    public Student Student { get; set; } // Navigation property  
    public Course Course { get; set; }   // Navigation property  
}

这些类表示演示关系所需的基本结构。在实际应用程序中,您还需要使用实体框架(或其他 ORM)特定配置(如 Fluent API 或数据注释)配置这些关系,以确保关系在数据库中正确映射。

2. 一对一关系的 LINQ 查询

让我们从最简单的关系开始。考虑两个实体:和 ,每个用户都有一个唯一的配置文件。UserUserProfile

查询语法:

var userWithProfile = from user in context.Users  
                      join profile in context.UserProfiles  
                      on user.ID equals profile.UserID  
                      select new { user.Name, profile.ProfilePicture };

方法语法:

var userWithProfile = context.Users  
                             .Join(context.UserProfiles,  
                                   user => user.ID,  
                                   profile => profile.UserID,  
                                   (user, profile) => new { user.Name, profile.ProfilePicture });

在此转换后的查询中:

  • context.Users以及正在连接的两个集合。context.UserProfiles

  • lambda 表达式 和 用于指定连接条件(from 与 from 匹配)。user => user.IDprofile => profile.UserIDIDUsersUserIDUserProfiles

  • 结果选择器创建一个匿名对象,其中包含 from 和 from 。(user, profile) => new { user.Name, profile.ProfilePicture }NameUserProfilePictureUserProfile

此 LINQ 查询检索每个用户及其关联的配置文件图片。

3. 掌握使用 LINQ 的一对多关系

一对多关系在数据库中很常见。例如,一个实体可能与多个 .CustomerOrders

查询语法:

var customerOrders = from customer in context.Customers  
                     join order in context.Orders  
                     on customer.ID equals order.CustomerID  
                     select new { customer.Name, order.OrderID, order.TotalAmount };

方法语法:

var customerOrders = context.Customers  
                            .Join(context.Orders,  
                                  customer => customer.ID,  
                                  order => order.CustomerID,  
                                  (customer, order) => new { customer.Name, order.OrderID, order.TotalAmount });

在此查询中:

  • context.Customers以及正在连接的两个集合。context.Orders

  • lambda 表达式并指定连接键(from 和 from )。customer => customer.IDorder => order.CustomerIDIDCustomersCustomerIDOrders

  • 最终的 lambda 表达式使用 from 、 和 from 构造一个新的匿名对象。(customer, order) => new { customer.Name, order.OrderID, order.TotalAmount }NameCustomerOrderIDTotalAmountOrder

此查询将为您提供客户列表及其各自的订单。

4. 驾驭多对多关系

多对多关系更为复杂。考虑 和 ,其中学生可以注册多门课程,并且每门课程可以有多个学生。StudentsCourses

在这里,通常使用像 这样的中间表来管理这种关系。StudentCourses

查询语法:

var courseEnrollments = from student in context.Students  
                        join sc in context.StudentCourses on student.ID equals sc.StudentID  
                        join course in context.Courses on sc.CourseID equals course.ID  
                        select new { student.Name, course.CourseName };

方法语法:

var courseEnrollments = context.Students  
    .Join(context.StudentCourses,   
          student => student.ID,   
          sc => sc.StudentID,   
          (student, sc) => new { student, sc })  
    .Join(context.Courses,   
          studentAndSc => studentAndSc.sc.CourseID,   
          course => course.ID,   
          (studentAndSc, course) => new { studentAndSc.student.Name, course.CourseName });

在此查询中:

  • 第一个连接。它将每个学生与其课程注册相关联。JoinStudentsStudentCourses

  • 第二个将此中间结果链接到 .它将注册的课程与每个学生相关联。JoinCourses

  • 结果选择器将创建一个匿名对象,其中包含学生的姓名和课程名称。(studentAndSc, course) => new { studentAndSc.student.Name, course.CourseName }

此 LINQ 查询有助于检索每个学生注册的课程。

5. 高级方案和提示

1. 关系中的过滤和排序

假设您要查找特定客户的所有订单并按日期对它们进行排序。以下是使用这两种语法的方法。

查询语法:

var sortedOrders = from order in context.Orders  
                   where order.CustomerID == specificCustomerId  
                   orderby order.OrderDate  
                   select order;

方法语法:

var sortedOrders = context.Orders  
                   .Where(order => order.CustomerID == specificCustomerId)  
                   .OrderBy(order => order.OrderDate);

2. 急切加载与延迟加载示例

急速加载在单个查询中获取相关数据,而延迟加载则按需获取相关数据。下面是一个急切加载的示例:

查询语法:

var customersWithOrders = from customer in context.Customers  
                          .Include(c => c.Orders)  
                          select customer;

方法语法:

var customersWithOrders = context.Customers  
                          .Include(c => c.Orders);

3. 性能注意事项和优化

了解如何优化 LINQ 查询至关重要,尤其是对于大型数据集。

  • 使用投影:仅选择所需字段,而不是获取整个实体。

  • 避免 N+1 查询:在多对多关系中,请确保不会对每个项目执行其他查询。

  • 批处理操作:对于更新或插入,请考虑使用批处理操作以减少数据库往返。

优化投影示例:

查询语法:

var optimizedData = from student in context.Students  
                    select new { student.Name, student.Department };

方法语法:

var optimizedData = context.Students  
                    .Select(student => new { student.Name, student.Department });

4. 只读方案的 AsNoTracking

对于只读方案,使用可以通过不跟踪更改来提高性能。AsNoTracking

查询语法:

var readOnlyData = context.Students  
                         .AsNoTracking()  
                         .Where(s => s.Year == 2);

方法语法:

var readOnlyData = from student in context.Students.AsNoTracking()  
                   where student.Year == 2  
                   select student;

结论:使用 LINQ 提升数据库查询技能

LINQ 是 .NET 库中的一种通用工具,用于处理各种类型的数据库关系。无论是简单的一对一关系还是复杂的多对多方案,LINQ 都能简化和简化流程,使代码更加高效和可维护。

如果你喜欢我的文章,请给我一个赞!谢谢

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值