親テーブルと子テーブルの2つのテーブルがあります。子テーブルには、列の並べ替え順序(数値)があります。 EFのサポートが欠如しているため、並べ替え順序を公開せずにIListを含む並べ替え順序を永続化します(参照: Entity Framework永続的な子コレクションの並べ替え順序 )。子クラスにもプロパティSortOrderがあるため、iソート順で子供を保存できます。
参照された質問の講師とは対照的に、常にソートされた子をロードしようとします。だから私が期待する親インスタンスをロードすると、子コレクションはソート順にソートされます。 Code First Fluent APIとPOCOでこの動作を実現するにはどうすればよいですか?
ヒント:子コレクションで.Sort(...)を呼び出すことはできません。
EFの熱心なローディングもレイジーローディングも順序付けやフィルタリングをサポートしていないため、これを直接達成することはできません。
オプションは次のとおりです。
OrderBy
を使用できます2番目のオプションは、明示的なロードで使用できます。
var parent = context.Parents.First(...);
var entry = context.Entry(parent);
entry.Collection(e => e.Children)
.Query()
.OrderBy(c => c.SortOrder)
.Load();
単一のクエリでこれを効率的に行うことができます。文法はぎこちないです。
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は、匿名オブジェクトを中心に設計されています。匿名オブジェクトが作成されると、P
とC
に割り当てられたオブジェクトの両方が追跡されます。つまり、それらの関係が記録され、その状態はEF変更トラッカーによって維持されます。 C
はP
の子のリストであるため、匿名オブジェクトで明示的に関連するように要求していなくても、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;