2013-03-26 63 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

相關問題