找出实体是否附加到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 

附着之前

请注意,如果您的上下文禁用了更改跟踪 ,那么询问ObjectStateManagerChangeTracker可能会返回该对象不在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();