Julie Lerman は、彼女の著書Programming Entity Framework: DbContextで、集計全体を更新する方法に対処する優れた方法を提供しています。
彼女が書いているように:
切断されたエンティティ グラフがサーバー側に到着すると、サーバーはエンティティの状態を認識しません。コンテキストが各エンティティの状態を認識できるように、状態を検出する方法を提供する必要があります。
この技法は と呼ばれpainting the state
ます。
そのためには、主に次の 2 つの方法があります。
- モデルに関する知識を使用してグラフを反復処理し、各エンティティの状態を設定します
- 状態を追跡するための一般的なアプローチを構築する
2 番目のオプションは非常に優れており、モデル内のすべてのエンティティが実装するインターフェイスを作成します。ジュリーはIObjectWithState
、エンティティの現在の状態を伝えるインターフェースを使用します。
public interface IObjectWithState
{
State State { get; set; }
}
public enum State
{
Added,
Unchanged,
Modified,
Deleted
}
最初に行う必要があるのは、イベントをフックUnchanged
するコンストラクターをクラスに追加して、DB から取得したすべてのエンティティの状態を自動的に設定することです。Context
public YourContext()
{
((IObjectContextAdapter)this).ObjectContext
.ObjectMaterialized += (sender, args) =>
{
var entity = args.Entity as IObjectWithState;
if (entity != null)
{
entity.State = State.Unchanged;
}
};
}
次にOrder
、OrderItem
クラスを変更してIObjectWithState
インターフェイスを実装しApplyChanges
、ルート エンティティをパラメーターとして受け入れるこのメソッドを呼び出します。
private static void ApplyChanges<TEntity>(TEntity root)
where TEntity : class, IObjectWithState
{
using (var context = new YourContext())
{
context.Set<TEntity>().Add(root);
CheckForEntitiesWithoutStateInterface(context);
foreach (var entry in context.ChangeTracker
.Entries<IObjectWithState>())
{
IObjectWithState stateInfo = entry.Entity;
entry.State = ConvertState(stateInfo.State);
}
context.SaveChanges();
}
}
private static void CheckForEntitiesWithoutStateInterface(YourContext context)
{
var entitiesWithoutState =
from e in context.ChangeTracker.Entries()
where !(e.Entity is IObjectWithState)
select e;
if (entitiesWithoutState.Any())
{
throw new NotSupportedException("All entities must implement IObjectWithState");
}
}
最後になりましたが、呼び出す前にグラフ エンティティの正しい状態を設定することを忘れないでくださいApplyChanges
;-) (同じグラフ内で状態Modified
と状態を混在させることもできます。)Deleted
ジュリーは、彼女の著書でさらに先へ進むことを提案しています。
変更されたプロパティを追跡する方法をより細かくしたいと思うかもしれません。エンティティ全体を変更済みとしてマークするのではなく、実際に変更されたプロパティのみを変更済みとしてマークしたい場合があります。クライアントは、エンティティを変更済みとしてマークするだけでなく、どのプロパティが変更されたかを記録する責任もあります。これを行う 1 つの方法は、変更されたプロパティ名のリストを状態追跡インターフェイスに追加することです。
しかし、私の答えはすでに長すぎるので、もっと知りたければ彼女の本を読んでください ;-)