2013-03-26 93 views
12

我试图删除一个对象使用EntityFramework 5,但我得到这个错误。 该对象无法删除,因为它在ObjectStateManager中找不到
我正在使用Remove()方法,因为DeleteObject()不存在于EF5中。 任何人都可以帮助我失去什么?该对象无法删除,因为它没有在实体框架中的ObjectStateManager中找到5

这不适用于删除

localDb.Customers.Remove(new Customer() { CustomerId = id }); 
       localDb.SaveChanges(); 

另一件事我从MSDN试图将状态改为已删除工作。但是这里给出了一个错误,说明所有的字段都应该存在。是否有必要获得完整的记录然后删除?

var customer = new Customer(){ CustomerId = id }; 
       localDb.Customers.Attach(customer); 

       localDb.Entry(customer).State = EntityState.Deleted; 
       localDb.SaveChanges(); 

任何输入?

回答

24

您可以从数据库读取的行,然后将其删除,但这会导致2个往返到数据库。

如果您希望在一次打击中执行此操作,则只要实体尚未加载到上下文中,您的第二个版本将与Attach一起工作。

您得到的错误是由任何数据库写入之前运行的EF验证引起的。

您可以暂时将其关闭是这样的:

bool oldValidateOnSaveEnabled = localDb.Configuration.ValidateOnSaveEnabled; 

try 
{ 
    localDb.Configuration.ValidateOnSaveEnabled = false; 

    var customer = new Customer { CustomerId = id }; 

    localDb.Customers.Attach(customer); 
    localDb.Entry(customer).State = EntityState.Deleted; 
    localDb.SaveChanges(); 
} 
finally 
{ 
    localDb.Configuration.ValidateOnSaveEnabled = oldValidateOnSaveEnabled; 
} 
+0

感谢Nicholas,只是为了改进我的概念,为什么在EF端而不是在SQL端进行验证?这是一个命中的唯一方法,因为这个设置似乎对我来说很重要...如果有任何不正确的请纠正我。 – 2013-03-26 13:47:37

+0

到目前为止,这是唯一的答案,我相信没有造成2次前往Db。因此将其标记为性能方面的答案。 – 2013-07-08 13:01:54

+0

northwind.Entry(entity).State = System.Data.Entity.EntityState.Deleted; 固定为我,谢谢 – balron 2014-10-07 21:13:13

2

你能做到吗?

var customer = localDb.Customers.Single(o => o.CustomerId == id); 
localDb.Customers.Remove(customer); 
localDb.SaveChanges(); 
+0

是的,但我们不能删除只有主键的实体吗? ,我们可以在这些行上设置主键或其他东西吗? – 2013-03-26 13:44:35

+0

你在第二个例子中有什么实际工作,你有没有试图设置所需字段的临时默认值并删除?它们的值不应该因为无论如何您都要删除对象,主要(实体)键就是所有需要准确的。 – 2013-03-26 13:57:14

6

如果您检索从数据库然后对象它已经连接到上下文,因此您可以通过删除:

db.myTable.Remove(model); 


如果您刚刚收到编辑模型或删除视图或自己生成它以避免2次数据库访问,然后EF不知道它,你会得到上面的错误(..在ObjectStateManager没有找到。)所以你设置其状态为“已删除”的通知EF

//generate it yourself if not posted from edit/delete view 
//var model = new Model { Id = 123 }; 

//set to delete 
db.Entry(model).State = EntityState.Deleted; 
db.SaveChanges(); 
0
public T Delete<T>(T obj) where T : class 
     { 
      T existing = context.Set<T>().Find(GetKeys(obj, context)); 

      if (existing != null) 
      { 
       context.Set<T>().Remove(existing); 
       context.SaveChanges(); 
       return existing; 
      } 
      return null; 
     } 

private object[] GetKeys<T>(T entity, DbContext context) where T : class 
     { 
      ObjectContext objectContext = ((IObjectContextAdapter)context).ObjectContext; 
      ObjectSet<T> set = objectContext.CreateObjectSet<T>(); 
      var keyNames = set.EntitySet.ElementType 
                 .KeyMembers 
                 .Select(k => k.Name).ToArray(); 
      Type type = typeof(T); 

      object[] keys = new object[keyNames.Length]; 
      for (int i = 0; i < keyNames.Length; i++) 
      { 
       keys[i] = type.GetProperty(keyNames[i]).GetValue(entity, null); 
      } 
      return keys; 
     } 
0

我知道这个问题是很老,但没有以上,因为工作对我来说我一次从多个类/服务中删除寄存器,并且每个都实例化它自己的数据库连接上下文。

我做了什么来解决这个问题,是将第一个创建的上下文发送到其他要访问数据库的类/服务。

例如,我的serviceA将删除其中的一些寄存器,并呼叫serviceBserviceC对其寄存器执行相同操作。

然后,我会删除serviceA我的寄存器和对serviceA创建的上下文作为参数传递给serviceBserviceC

相关问题