我正在尝试检索包含(作为每门课程的属性)部门列表的课程列表。数据库模式由课程,部门和course_departments连接表组成。
我当前的查询(删除了不必要的位)如下:
ctx.Courses
.Select(c => new Course
{
ID = c.ID,
Departments = c.CourseDepartments.Select(cd => new Department(cd.Department))
}
)
这样可行,但在分析器中检查后,它正在执行新查询以获取每个课程的部门。如何编写此查询以将其作为单个SQL查询执行?
答案 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,这可能会对你有所帮助。