エンティティをコンテキストにアタッチしようとすると、例外が発生します
同じキーを持つオブジェクトがObjectStateManagerに既に存在します。 ObjectStateManagerは、同じキーを持つ複数のオブジェクトを追跡できません
これは予想される動作です。
しかし、ObjectStateManagerがそれをどのように知っているのか知りたいですか?前に自分でこのチェックをしたい
DbContext APIを使用している場合(ef-code-firstに言及した場合)、単純に使用できます:
context.YourEntities.Local.Any(e => e.Id == id);
またはより複雑
context.ChangeTracker.Entries<YourEntity>().Any(e => e.Entity.Id == id);
ObjectContext APIの場合、次を使用できます。
context.ObjectStateManager.GetObjectStateEntries(~EntityState.Detached)
.Where(e => !e.IsRelationship)
.Select(e => e.Entity)
.OfType<YourEntity>()
.Any(x => x.Id == id);
オブジェクトが既にアタッチされているかどうかを心配せずにコンテキストからオブジェクトを取得するための拡張メソッドは次のとおりです。
public static T GetLocalOrAttach<T>(this DbSet<T> collection, Func<T, bool> searchLocalQuery, Func<T> getAttachItem) where T : class
{
T localEntity = collection.Local.FirstOrDefault(searchLocalQuery);
if (localEntity == null)
{
localEntity = getAttachItem();
collection.Attach(localEntity);
}
return localEntity;
}
ただ電話する:
UserProfile user = dbContext.UserProfiles.GetLocalOrAttach<UserProfile>(u => u.UserId == userId, () => new UserProfile { UserId = userId });
小切手
entity.EntityState == System.Data.EntityState.Detached
取り付ける前に
コンテキストで変更の追跡が無効になっている場合、ObjectStateManager
またはChangeTracker
を要求すると、オブジェクトがObjectContext
にないことを返す場合があることに注意してください実際に既に存在している場合。したがって、そのようなオブジェクトを添付しようとすると、例外が発生します。
_context.Set<T>.Local.Any(e => e.Id == id);
_
変更追跡が無効になっている場合、イベントが機能します。
オブジェクトのタイプがわからない場合は、さまざまなアプローチがあります。リフレクションまたはこのような他の手法を使用してメソッドを定義しますint GetIdOf(object entity){...}
または、次のようにクラスで使用されるインターフェイスを定義します
_public interface IMyEntity
{
int Id{get;set;}
}
_
このように使用します:
_context.Set(e.GetType()).Local.Cast<IMyEntity>().Any(e => e.Id == id);
_
「Any」拡張メソッドを使用してdbContextを照会できます。
bool alreadyInDB = dbContext.Entity.Where(a=>a.ID==myEntity.id).Any();