0

適切な Include ステートメントを追加して熱心な読み込みを強制し、データベースに対して行うクエリの数を減らすことで、いくつかの db 層関数を高速化しようとしています。

ただし、90% のケースで、必要なインクルードを入力するための正しい「開始位置」にいないという問題に遭遇します。

私が思いつくことができる最も簡単な例:

DepartmentCourse、およびStudentエンティティがあり、それらの間に多対多の関係があります(一部のコースから複数の部門へ)。

今、私は機能を持っています

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)

正しいインクルードを指定できるようにするためだけに、このような回避策を実行しなければならないのは、かなりばかげているようです。インクルードの多くの例を見て、stackoverflow で多くの質問を検索しましたが、この問題を抱えている人を実際に見つけることはできません。

4

2 に答える 2

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();

派生エンティティ (POCO ではない)を使用ObjectContextしている場合:EntityObject

objectContext.Departments.Attach(dep);
dep.Courses.Attach(dep.Courses.CreateSourceQuery()
    .Include("Students")
    .Where(c => c.level == "Master")
    .ToList());

ObjectContextPOCOを使用している場合は可能ですが、少し面倒です。

データベース内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の SQL への変換にはかなりのコストがかかるため、必ずしもパフォーマンスが向上するとは限りません。courseIDs

于 2013-06-27T18:49:01.050 に答える