我正在尝试通过添加适当的Include语句来加速我的数据库层功能,以强制执行加载并减少我对数据库进行的查询次数。
然而,在90%的情况下,我遇到的问题是我没有在正确的“起始位置”进入我想要的包含。
我能提出的最简单的例子:
我有部门,课程和学生实体,他们之间有多对多关系(以下某些课程涉及多个部门)。
现在我有一个功能
GetMasterCourses(Department dep)
执行类似
return dep.Courses.Where(c => c.level == "Master")
问题是:我如何告诉EF加载与每个查询课程相关的所有学生?
我找到的唯一解决方案是:
courseIDs = dep.Courses
.Where(c => c.level == "Master").Select(c => c.courseID)
dbcontext.Courses
.Include("Students")
.Where(c => courseIDs.Contains(c.courseID) and c.level == Master)
为了能够指定正确的Include,必须做这样的解决方案似乎很愚蠢。我已经看了很多关于Include的例子,并在stackoverflow上搜索了很多问题,但是找不到任何有这个问题的人,尽管这似乎是一个很常见的问题。
答案 0 :(得分:1)
我不明白为什么要选择ID。看起来你可能只是:
var courses = dep.Courses
.Include(i => i.Students)
.Where(c => c.level == "Master")
.ToList() // or whatever
答案 1 :(得分:1)
如果您使用DbContext
(EF> = 4.1):
dbContext.Departments.Attach(dep);
dep.Courses = dbContext.Entry(dep).Collection(d => d.Courses).Query()
.Include(c => c.Students)
.Where(c => c.level == "Master")
.ToList();
如果您将ObjectContext
与EntityObject
派生实体(非POCO)一起使用:
objectContext.Departments.Attach(dep);
dep.Courses.Attach(dep.Courses.CreateSourceQuery()
.Include("Students")
.Where(c => c.level == "Master")
.ToList());
如果您将ObjectContext
与POCO it's possible but a bit hairy一起使用。
上述所有查询实际上与您的查询不同,因为您的dep.Courses
集合可能不包含与数据库中的部门dep
相关的所有课程。 (谁知道你加载后是否从dep.Courses
集合中删除了一个课程?)在这种情况下,我担心你的查询是唯一的出路。
因为你在谈论性能和数据库请求优化:如果你想避免再次加载课程的开销(你已经在内存中),你也可以尝试:
courseIDs = dep.Courses
.Where(c => c.level == "Master").Select(c => c.courseID);
var studentDict = dbcontext.Courses
.Where(c => courseIDs.Contains(c.courseID))
.Select(c => new
{
courseID = c.courseID,
Students = c.Students
})
.ToDictionary(x => x.courseID, x => x.Students);
foreach (var course in dep.Courses)
course.Students = studentDict[course.courseID];
它加载的数据较少,但不一定具有更高的性能,因为Contains
会为大型courseIDs
集合转换成SQL的成本很高。