Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/svn/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linq 超高添加包括(急加载)到正确位置_Linq_Entity Framework 4_Eager Loading - Fatal编程技术网

Linq 超高添加包括(急加载)到正确位置

Linq 超高添加包括(急加载)到正确位置,linq,entity-framework-4,eager-loading,Linq,Entity Framework 4,Eager Loading,我正试图通过添加适当的Include语句来加速我的一些db层函数,以强制快速加载并减少对数据库的查询数量 然而,在90%的情况下,我遇到的问题是,我没有在正确的“起始位置”输入我想要的包含项 我能想到的最简单的例子是: 我有部门、课程和学生实体,它们之间存在多对多关系(下面的一些课程与多个部门) 现在我有一个函数 GetMasterCourses(Department dep)哪个功能类似于 return dep.Courses.Where(c=>c.level==“Master”) 问题是:我

我正试图通过添加适当的Include语句来加速我的一些db层函数,以强制快速加载并减少对数据库的查询数量

然而,在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而不得不做这样一个变通方法,这似乎相当愚蠢。我查看了许多包含的示例,并搜索了许多有关stackoverflow的问题,但没有找到有此问题的人,尽管这似乎是一个非常常见的问题。

我不明白您为什么选择ID。看起来你可以:

var courses = dep.Courses
  .Include(i => i.Students)
  .Where(c => c.level == "Master")
  .ToList() // or whatever

如果您使用的是
DbContext
(EF>=4.1):

如果将
ObjectContext
EntityObject
派生实体(非POCO)一起使用:

如果将
ObjectContext
与POCO一起使用

上述所有查询实际上与您的查询不同,因为您的
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];

它加载的数据更少,但性能不一定更高,因为对于大型
CourseID
集合,
Contains
需要大量的转换成SQL的成本。

因此,您的输入是
部门
,这(我假设)不是上下文的一部分。您期望的返回类型是什么?当您加载
部门
时,您是否渴望加载
课程
学生
?部门是函数的参数,例如由
dbcontext.Departments.First()检索。在这段时间里,课程和学生们确实不感兴趣。预期的返回类型将是IQueryable,因此一组课程将加载相关的学生集合。
dep.courses.Include(i=>i.Students)
正是我想要做的,但EF不允许这样做。似乎我是ObjectQuery对象(即context.Courses)上唯一的一个包含。我不能在IQueryable类关联集(dep.Courses)上使用include函数。我使用的是EF4而不是EF5,但我在互联网上还没有看到一个能像这样使用include的例子。如果可能的话,请告诉我。
objectContext.Departments.Attach(dep);
dep.Courses.Attach(dep.Courses.CreateSourceQuery()
    .Include("Students")
    .Where(c => c.level == "Master")
    .ToList());
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];