タイトルが示唆するように、私はinclude節と組み合わせてwhere節を行う方法を探しています。
私の状況は次のとおりです。私は、コードの匂いに満ちた大規模なアプリケーションのサポートを担当しています。コードの変更が多すぎるとどこでもバグが発生するため、最も安全なソリューションを探しています。
オブジェクトBusとオブジェクトPeopleがあるとします(バスにはナビゲーションプロップコレクションのPeopleがあります)。私のクエリでは、起きている乗客だけがいるすべてのバスを選択する必要があります。これは単純なダミーの例です
現在のコードでは:
var busses = Context.Busses.Where(b=>b.IsDriving == true);
foreach(var bus in busses)
{
var passengers = Context.People.Where(p=>p.BusId == bus.Id && p.Awake == true);
foreach(var person in passengers)
{
bus.Passengers.Add(person);
}
}
このコードの後、コンテキストは破棄され、呼び出し元のメソッドで結果のバスエンティティがDTOクラス(エンティティの100%コピー)にマッピングされます。
このコードにより、No-GoであるDBへの複数の呼び出しが発生するため、このソリューションを見つけました ON MSDN Blogs
結果をデバッグするときにこれはうまく機能しましたが、エンティティがDTO(AutoMapperを使用)にマップされると、コンテキスト/接続が閉じられ、オブジェクトをロードできないという例外が発生します。 (コンテキストは常に閉じているため、これを変更することはできません:()
そのため、選択した乗客が既に読み込まれていることを確認する必要があります(ナビゲーションプロパティのIsLoadedもFalseです)。 Passengersコレクションを調べた場合、Countも例外をスローしますが、フィルターされたオブジェクトを含む「ラップされた関連エンティティ」と呼ばれるPassegersのコレクションにもコレクションがあります。
これらのラップされた関連エンティティをコレクション全体にロードする方法はありますか? (オートマッパーマッピング設定はアプリケーション全体で使用されるため、変更できません)。
アクティブな乗客を取得する別の方法はありますか?
どんなヒントでも大歓迎です...
Gert Arnoldの回答は、データが熱心にロードされないため機能しません。しかし、それを単純化し、ロードされた場所を削除すると。 execute SQLは両方のケースですべての乗客を返すため、これは本当に奇妙です。そのため、結果をエンティティに戻すときに問題が発生するはずです。
Context.Configuration.LazyLoadingEnabled = false;
var buses = Context.Busses.Where(b => b.IsDriving)
.Select(b => new
{
b,
Passengers = b.Passengers
})
.ToList()
.Select(x => x.b)
.ToList();
たくさんの苦労の末、Gert Arnoldの仕事の答えに! Gert Arnoldが提案したように、Lazy Loadingを無効にし、OFFにする必要があります。前の開発者はレイジーローディングを愛していたので、これによりアプリケーションにいくつかの追加の変更が必要になります-_-
免責事項:私はプロジェクトの所有者です Entity Framework Plus
EF + Query IncludeFilter機能により、関連するエンティティをフィルタリングできます。
var buses = Context.Busses
.Where(b => b.IsDriving)
.IncludeFilter(x => x.Passengers.Where(p => p.Awake))
.ToList();
Wiki: EF + Query IncludeFilter