找出实体是否附加到dbContext的最合理的方法是什么?
当我尝试附加实体上下文我得到一个exception
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
即使它实际上已经在那里。 因此,如果您尝试附加此对象,则会引发exception。
context.Set<T>.Local.Any(e => e.Id == id);
如果更改跟踪被禁用,则工作事件。
如果你不知道对象的types,有各种各样的方法,要么使用reflection或像这样的其他技术定义一个方法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();