この質問の前に、次のように説明します。インターネット上には、古い「同じキーを持つオブジェクトが既に ObjectStateManager に存在する」という問題に関する投稿が 100 万件あることを知っています。私のシナリオはもう少し複雑だと思います。
DbContext を作成し、呼び出されたリポジトリに渡す UnitOfWork クラスがあります。私が使用しているパターンは、ASP.NET サイトの Unit of Work チュートリアルに厳密に従っています。チュートリアルとは異なり、私のリポジトリはビジネス エンティティを取り込み、それらをデータ エンティティにマップし、CRUD アクションを実行します。マイ ビジネス ロジックは、ビジネス エンティティでのみ機能します。サンプルの Business Manager クラスで私がやろうとしていることは次のとおりです。
_unitOfWork.Repository.Add(entity);
_unitOfWork.Save(); // context.SaveChanges() under the hood
...Perform some operations on the model...
_unitOfWork.Repository.Update(entity);
_unitOfWork.Save();
以下は、リポジトリの Update メソッドのサンプルです。
public virtual void Update(entity)
{
var dataEntity = // map from business entity to data;
_context.Entry(dataEntity).State = EntityState.Modified;
}
最後の行で明らかに失敗します。ここで私の混乱が始まります:
- エンティティの状態は切り離されています
- State を Modified または Unchanged に変更しようとすると、上記の ObjectStateManager 例外が発生します。
- コンテキストからエンティティをデタッチしようとすると (((IObjectContextAdapter)_context).ObjectContext.Detach(entity);) エンティティがコンテキストにアタッチされていないという例外が発生するため、エンティティをデタッチできません。非常に紛らわしいです(確かに、私が見逃している基本的なものです)。
- 他の多くの投稿では、データベース呼び出しを行い、リポジトリ内のそのエンティティを更新してから、_unitOfWork.Save() を提案しています。私はこのアプローチが好きではありません。エンティティを更新するために不要なネットワーク呼び出しを行う必要はありません。
リポジトリの Update メソッドは、2 つのシナリオを処理する必要があります。1) 現在コンテキストによって追跡されていないエンティティの更新、および 2) 現在コンテキストによって追跡されているエンティティの更新。2番目の部分は私が苦労しているものです。
どんな助けや洞察も大歓迎です。
ありがとう!