LINQ嵌套选择会导致多个SQL查询

时间:2015-03-25 19:21:38

标签: c# linq linq-to-entities

我正在尝试检索包含(作为每门课程的属性)部门列表的课程列表。数据库模式由课程,部门和course_departments连接表组成。

我当前的查询(删除了不必要的位)如下:

ctx.Courses
    .Select(c => new Course
        {
            ID = c.ID,
            Departments = c.CourseDepartments.Select(cd => new Department(cd.Department))
        }
     )

这样可行,但在分析器中检查后,它正在执行新查询以获取每个课程的部门。如何编写此查询以将其作为单个SQL查询执行?

2 个答案:

答案 0 :(得分:1)

因为您使用嵌套选择,SQL提供程序会将其转换为等效的SQL(使用单独的/嵌套查询)。你可以使用像这样的Join方法来纠正这个问题;

ctx.Courses.Join(ctx.CourseDepartments,
                 c => c.ID, cd => cd.cID,
                 (c, cd) => new {
                     Course = c,
                     dID = cd.dID
                 }).Join(ctx.Departments,
                         c => c.dID,
                         d => d.ID,
                         (c, d) => new {
                               Course = c.Course,
                               Department = d
                 });

我没有测试过示例代码,但这是基本的想法。我几乎专门使用方法语法,但查询语法实际上对于连接更加清晰,你可以在这里比较它们How do I convert multiple inner joins in SQL to LINQ?这是我用来制作我的解决方案。

总结问题的原因和解决方案;如果您需要一个查询,您必须从课程加入课程部门到部门,SQL提供程序不能暗示您的嵌套选择应该转换为几个连接。要在LINQ中编写查询,您应该使用最相似的可用SQL构造,在这种情况下,它是一个连接。可能还有其他方法来编写查询,这将隐式地通知查询提供程序连接,但这是编写所需查询的显式方式。

答案 1 :(得分:0)

我写了一些可能适合您的解决方案的代码。 实体定义并不完全相同,但事实并非如此。

var query = context.Courses.AsQueryable();
query = query.Include(i => i.CoursesDepartments);
query = query.Include(i => i.CoursesDepartments.Select(cd => cd.Departments));

var newQuery = query.Select(course =>  new 
{
    ID = course.ID,
    Departments = course.CoursesDepartments.Select( cd => cd.Departments),
});

var result = query.ToList();

简而言之,Include函数告诉LINQ在获取Courses实体时应该加载哪些相关实体,否则它们将是Lazy Loaded。

提示:我知道有些人用LINQPad来学习LINQ,这可能会对你有所帮助。