オブジェクトのセットにEFを使用していて、他の2つのテーブルの一致するエントリを使用して1つのタイプのオブジェクトをクエリしたいと思います。これは、クエリをXML出力にダンプするためのものです。元のデータでは、各従業員が常にComputerオブジェクトのインスタンスを1つ以上持っていたため(以下のソリューション#2)、最初は結合を使用しましたが、必ずしもそうとは限りません。
ここでの目的のために、想像してみてください。
- Employeeオブジェクト、
- 各従業員にはEmployeeType(いくつかの固定エントリ)と
- 各従業員には、0個以上のコンピューターオブジェクト(通常は0〜3)があります。
- 各コンピューターは1人の従業員に属しており、すべての従業員がコンピューターを持っているわけではありません。
- 各従業員には、検索の基礎となる基準(部門など)があります。
だから私はいくつかの可能な解決策を見ました:
ループ内でEmployee.Computer.Load()を使用しますが、行数が10,000を超えると、パフォーマンスが大幅に低下します。
クエリで結合を使用しますが、コンピューターを持たないすべての従業員が除外されます。
Linq to Entitiesを使用
しますが、これには#1のオーバーヘッドがあるようです。コンピューターをロードすると、各従業員のデータベースにヒットします。2番目のクエリ(Computer.Employee.Divisionと一致するすべてのコンピューター)を使用してから、Employeeループで、指定された従業員の任意のコンピューターを追加します。これを実装しているときに、( ToList()を使用して)2番目のクエリを実行するだけで、EFが正しいEmployee.Computerリストに必要なオブジェクトを入力することがわかりました。
ここで、#4は10k以上ではなく2つのデータベースヒットのみでデータをロードし、EntityFrameworkは実際にオブジェクトを照合して、すべての関係を作成します。
私の質問:
- #4では、EFがEmployee.Computerリストにデータを入力するという事実は、私が信頼できるものですか?もしそうなら、私にドキュメントを教えてもらえますか?
- #4より良い方法はありますか?
更新:まあ、バガー。申し訳ありませんが、私は単にそれを吹きました。私は「Computer」テーブルとの関係に焦点を合わせていましたが、最初にnullをテストせずに明示的なEmployee.EmployeeTypeReference.Load()を使用していたという事実を見逃したため、「Computer」リストはまったく問題になりませんでした。
これは、いくつかのパフォーマンステストを実行し、Craigのソリューションをミックスに追加したときにのみ見つかりました。実際、レコードは「従業員」や「コンピューター」ではなく抽象化であり、私は(条件付きで)XML出力のすべてのフィールドを含みますが、名前、ID(PK)、ID(FK)に加えて小さいです。 「従業員」テーブルのINT。したがって、EFは投影よりもそれほど重くないオブジェクトを作成するため、パフォーマンスは同様であると私は推測しました。
とにかく、これが「経過」時間がこのクエリの前と結果のXMLが作成された後の違いであった場合の結果です。
ケース1:#2と同じですが、Include()ステートメントを使用します。
list = ve.Employee.Include("Computer").Include("EmployeeType").Where(e => e.Division.ID == divId).OrderBy(e => e.Name);
経過:4.96、5.05
ケース2:インラインLoad()を使用します:
list = ve.Employee.Where(e => e.Division.ID == divId).OrderBy(e => e.Name);
経過:74.62
ケース3:#4と同じですが、Include()ステートメントを使用します。
list = from e in ve.Employee.Include("Computer").Include("EmployeeType") where e.Division.ID == divId orderby e.Name select e;
経過:4.91、5.47
ケース4:インラインLoad()を使用します:
list = from e in ve.Employee where e.Division.ID == divId orderby e.Name select e;
経過:74.20
ケース5:* Include( "EmployeeType")を使用し、 "Computer"クエリを分離して、EFに関連付けさせます。
elist = ve.Employee.Include("EmployeeType").Where(te => te.Division.ID == divId).OrderBy(e => e.Name).ToList(); alist = ve.Alias.Where(a => a.Employee.Division.ID == divId).ToList();
経過:4.50、4.02
ケース6:クレイグの予測の提案:
elist = from te in ve.ThesaurusEntry where te.Division.ID==divID orderby te.Name select new { ID = te.ID, Name = te.Name, Type = te.EmployeeType.Name, Freq = te.Frequency, Aliases = from a in te.Alias select new { ID = a.ID, Name = a.Name } };
経過:0.73、1.25
結論
Load()は高価なので、Include()を使用するか、少なくともIsLoadedでテストしてください
投影は少し面倒ですが、EF修正よりも大幅に高速です。[「狭い」テーブルでのこの限定的なテストで]