2016-03-08 69 views
3

OK,我可以在EF6刪除單個項目這樣的分離:如何刪除EF6對象的列表時,對象從上下文

public void DeleteUserGroup(MY_GROUPS ug) 
{ 
    using (var context = new MYConn()) 
    { 
     var entry = context.Entry(ug); 
     if (entry.State == EntityState.Detached) 
     { 
      context.MY_GROUPS.Attach(ug); 
     } 

     context.MY_GROUPS.Remove(ug); 
     context.SaveChanges(); 
    } 
} 

如果此方法從傳遞的MY_GROUPS單個實例改變到List<MY_GROUPS>我將如何處理刪除?

會有一個更有效率的方法,然後只是做一個foreach並設置一次一個狀態?

UPDATE: 我已經在使用類似的方法,如上所述使用RemoveRange方法。 但是我得到一個錯誤:

The object cannot be deleted because it was not found in the ObjectStateManager.

我找對象的列表重視的背景下,這樣我可以刪除它們的最好方法。

+0

難道你沒有.RemoveRange你的上下文?如果我沒有記錯的話,你可以給RemoveRange一個你想要刪除的項目集合。 –

+0

我這樣做,我正在使用它。但是,我得到錯誤「對象無法刪除,因爲它沒有在ObjectStateManager中找到。」 – PrivateJoker

回答

1

爲了能夠刪除記錄,你需要確保你的ObjectContext正在跟蹤他們。現在你有分離的對象,你的上下文不瞭解它們,所以不可能刪除它們。刪除它們的一種方法就是像你說的那樣做,Attach將所有對象都放到上下文中,然後刪除它們。另一種方法是從數據庫中讀取記錄,這樣你可以刪除它們:但是

//Find all groups in database with an Id that is in your group collection 'ug' 
var groups = context.My_Groups.Where(g => ug.Any(u => u.Id == g.Id)); 
context.My_Groups.RemoveRange(groups); 
context.SaveChanges(); 

,請注意,即使使用RemoveRange,刪除命令將被髮送到數據庫項目要刪除。 RemoveRangeRemove之間的唯一區別是第一次只會調用DetectChanges一次,這可以真正提高性能。

+0

不讓我的ObjectContext跟蹤它們是不好的做法嗎?基本上我有一個類,每個方法創建(然後處置)的上下文。我按照該方法做我需要做的事情並按照我的方式行事。 – PrivateJoker

+0

取決於你如何得到團體。如果您在某個方法中獲取了某些組,則處理上下文,然後將這些具體化的組傳遞給另一個方法以刪除它們,這是*糟糕的做法。但是,如果您將羣組作爲json結果或某個網站的結果返回,您顯然無法對其進行處理。 –

+0

是的。我有這樣做的方法。我的UI使用POCO,在我的中間層,我將POCO映射到/從數據庫表中映射。所以我的EF類都是創建/處理上下文。我不相信我把它設置得最好,因爲我現在無法重用該類中的現有方法。 IE瀏覽器。在刪除列表的情況下,我通常會調用GetGroupList方法返回該列表,然後在刪除方法中刪除它們。現在我有一半不會調用該方法,並在我的刪除方法中執行所有操作。 – PrivateJoker

0

EntityFramework 6+使得.RemoveRange()更容易一點。

public void DeleteUserGroup(List<MY_GROUPS> ug) 
    { 
     using (var context = new MYConn()) 
     { 
      context.MY_GROUPS.RemoveRange(ug); 
      context.SaveChanges(); 
     } 
    } 
+0

我是這麼做的,我正在使用它。但是,我收到錯誤「對象無法刪除,因爲它沒有在ObjectStateManager中找到。」 – PrivateJoker

+0

試試我上面更新的代碼。 –

+1

該錯誤發生在RemoveRange調用上。我需要將該列表附加到上下文才能刪除它們。 (請參閱我上面的單個刪除) – PrivateJoker

2

您可以使用RemoveRange

context.MY_GROUPS.RemoveRange(context.MY_GROUPS.Where(x => x.columnName== "Foo")); 

您也可以使用ForEach這樣的:

context.MY_GROUPS.Where(x => x.columnName == "Foo").ToList().ForEach(context.DeleteObject); 
context.SaveChanges(); 

你也可以使用ObjectContext.ExecuteStoreCommand Method作爲另一種方法實現此目的。

+0

我做了,我正在使用它。但是,我得到錯誤「對象無法刪除,因爲它沒有在ObjectStateManager中找到。」 – PrivateJoker

+0

@JDS ...檢查我更新的答案。 –

1

遍歷您的收藏和設置Deleted狀態每個

groups.ForEach(group => ctx.Entry(group).State = EntityState.Deleted); 
ctx.SaveChanges(); 
+0

IMO,這是使用斷開連接的對象上下文的正確方法。 – Lex

0

通過使用由Alexander Deck提供的solution其中品牌是IEnumerable

context.Brands.RemoveRange(context.Brands.Where(cb => brands.Any(b => b.Id == cb.Id))); 

我得到了以下錯誤:

Unable to create a constant value of type 'SomeCompany.SomeApp.DB.Entities.Brand'. Only primitive types or enumeration types are supported in this context.

,它是由與轉換品牌DBSetIEnumerable解決AsEnumerable()擴展方法:

context.Brands.RemoveRange(context.Brands.AsEnumerable().Where(cb => brands.Any(b => b.Id == cb.Id))); 

這對我來說訣竅。

+0

請注意,調用AsEnumerable()將從數據庫中檢索完整的「品牌」表。這可能是可以接受的,但它取決於你的桌子尺寸... –

+0

感謝您的意見@GrégoryBourgin,我會確保明智地使用它 –