是否可以检查一个对象是否已经附加到entity framework中的数据上下文?

尝试附加已经通过context.AttachTo(...)连接到给定上下文的对象时出现以下错误:

ObjectStateManager中已经存在具有相同键的对象。 ObjectStateManager不能使用同一个键跟踪多个对象。

有没有一种方法可以实现以下几点:

context.IsAttachedTo(...)

干杯!

编辑:

杰森所提出的扩展方法非常接近,但对我的情况并不适用。

我正在尝试使用另一个问题的答案中概述的方法做一些工作:

如何从我的表中删除一行或多行使用Linq的实体*没有*首先检索行?

我的代码看起来有点像这样:

 var user = new User() { Id = 1 }; context.AttachTo("Users", user); comment.User = user; context.SaveChanges(); 

这工作正常,除非我为该用户做其他事情,我使用相同的方法,并尝试附加一个虚拟的User对象。 这失败了,因为我以前已经附加了这个虚拟用户对象。 我如何检查这个?

这就是我最后的结果,这非常好:

 public static void AttachToOrGet<T>(this ObjectContext context, string entitySetName, ref T entity) where T : IEntityWithKey { ObjectStateEntry entry; // Track whether we need to perform an attach bool attach = false; if ( context.ObjectStateManager.TryGetObjectStateEntry ( context.CreateEntityKey(entitySetName, entity), out entry ) ) { // Re-attach if necessary attach = entry.State == EntityState.Detached; // Get the discovered entity to the ref entity = (T)entry.Entity; } else { // Attach for the first time attach = true; } if (attach) context.AttachTo(entitySetName, entity); } 

你可以这样调用它:

 User user = new User() { Id = 1 }; II.AttachToOrGet<Users>("Users", ref user); 

这工作非常好,因为它就像context.AttachTo(...)除了你可以使用我每次上面引用的ID技巧。 您最终会得到以前连接的对象或您自己的对象被连接。 在上下文中调用CreateEntityKey可以确保它是很好的和通用的,并且即使对于没有进一步编码的复合键也能工作(因为EF已经可以为我们做这个了!)。

一个更简单的方法是:

  bool isDetached = context.Entry(user).State == EntityState.Detached; if (isDetached) context.Users.Attach(user); 

试试这个扩展方法(这是未经testing的和非常规的):

 public static bool IsAttachedTo(this ObjectContext context, object entity) { if(entity == null) { throw new ArgumentNullException("entity"); } ObjectStateEntry entry; if(context.ObjectStateManager.TryGetObjectStateEntry(entity, out entry)) { return (entry.State != EntityState.Detached); } return false; } 

鉴于您在编辑中描述的情况,您可能需要使用以下接受EntityKey而不是对象的重载:

 public static bool IsAttachedTo(this ObjectContext, EntityKey key) { if(key == null) { throw new ArgumentNullException("key"); } ObjectStateEntry entry; if(context.ObjectStateManager.TryGetObjectStateEntry(key, out entry)) { return (entry.State != EntityState.Detached); } return false; } 

要在您的情况下构build一个EntityKey ,请使用以下内容作为指导:

 EntityKey key = new EntityKey("MyEntities.User", "Id", 1); 

您可以通过使用属性User.EntityKey (从接口IEntityWithKey )从现有的User实例中获取EntityKey

使用您试图检查的对象的实体键:

 var entry = context.ObjectStateManager.GetObjectStateEntry("EntityKey"); if (entry.State == EntityState.Detached) { // Do Something } 

善良,

这不直接回答OP的问题,但这是我解决我的问题。

这是为那些正在使用DbContext而不是ObjectContext

  public TEntity Retrieve(object primaryKey) { return DbSet.Find(primaryKey); } 

DbSet.Find方法

查找具有给定主键值的实体。 如果具有给定主键值的实体存在于上下文中,则立即返回,而不向商店发出请求。 否则,向商店发出一个请求,要求具有给定主键值的实体,如果find,则将该实体附加到上下文并返回。 如果在上下文或商店中找不到实体,则返回null。

基本上,它返回给定primaryKey的附加对象,所以你只需要在返回的对象上应用更改以保持正确的实例。