web-dev-qa-db-ja.com

Entity Frameworkは、ソート順で子コレクションをロードします

親テーブルと子テーブルの2つのテーブルがあります。子テーブルには、列の並べ替え順序(数値)があります。 EFのサポートが欠如しているため、並べ替え順序を公開せずにIListを含む並べ替え順序を永続化します(参照: Entity Framework永続的な子コレクションの並べ替え順序 )。子クラスにもプロパティSortOrderがあるため、iソート順で子供を保存できます。

参照された質問の講師とは対照的に、常にソートされた子をロードしようとします。だから私が期待する親インスタンスをロードすると、子コレクションはソート順にソートされます。 Code First Fluent APIとPOCOでこの動作を実現するにはどうすればよいですか?

ヒント:子コレクションで.Sort(...)を呼び出すことはできません。

32
X181

EFの熱心なローディングもレイジーローディングも順序付けやフィルタリングをサポートしていないため、これを直接達成することはできません。

オプションは次のとおりです。

  • データベースからロードした後、アプリケーションのデータを並べ替える
  • 個別のクエリを実行して子レコードをロードします。別のクエリを使用すると、OrderByを使用できます

2番目のオプションは、明示的なロードで使用できます。

var parent = context.Parents.First(...);
var entry = context.Entry(parent);
entry.Collection(e => e.Children)
     .Query()
     .OrderBy(c => c.SortOrder)
     .Load();
38
Ladislav Mrnka

単一のクエリでこれを効率的に行うことができます。文法はぎこちないです。

var groups = await db.Parents
    .Where(p => p.Id == id)
    .Select(p => new
        {
            P = p,
            C = p.Children.OrderBy(c => c.SortIndex)
        })
    .ToArrayAsync();

// Query/db interaction is over, now grab what we wanted from what was fetched

var model = groups
    .Select(g => g.P)
    .FirstOrDefault();

説明

非同期メモ

私はたまたまここでasync拡張機能を使用しましたが、これはおそらく使用する必要がありますが、効率を損なうことなく同期クエリが必要な場合はawait/asyncを取り除くことができます。子の並べ替え。

最初のチャンク

デフォルトでは、データベースからフェッチされたすべてのEFオブジェクトが「追跡」されます。さらに、SQL Selectに相当するEFは、匿名オブジェクトを中心に設計されています。匿名オブジェクトが作成されると、PCに割り当てられたオブジェクトの両方が追跡されます。つまり、それらの関係が記録され、その状態はEF変更トラッカーによって維持されます。 CPの子のリストであるため、匿名オブジェクトで明示的に関連するように要求していなくても、EFはこれらをこの子としてロードしますとにかく、コレクションでスキーマ内に見られる関係のため

詳細については、上記を2つの個別のクエリに分割して、完全に異なるDb呼び出しで、親オブジェクトのみをロードし、次に子リストのみをロードすることができます。 EF変更トラッカーは、子を認識して親オブジェクトにロードします。

2番目のチャンク

EFをだまして、注文した子を返すようにしました。ここで、Parentオブジェクトのみを取得します。その子は、希望どおりに順番にアタッチされます。

Nulls and Tables as Sets

ここには、主にnullに関するベストプラクティスのための厄介な2ステップがあります。 2つのことを行うためにあります。

  • 可能な限り最後の瞬間まで、セット内のDBのことを考えてください。

  • Null例外を回避します。

言い換えれば、最後のチャンクは次のようになっていました。

var model = groups.First().P;

しかし、オブジェクトがデータベースに存在しなかった場合、それはnull参照例外で爆発します。 C#6では別の代替案が導入されますが、nullプロパティ合体演算子 -将来的には、最後のチャンクを次のものに置き換えることができます:

var model = groups.FirstOrDefault()?.P;
28
Chris Moschini