2010-01-13 91 views
25

我遇到了一個有趣的實體框架問題,並基於我必須用來解決它的代碼,我懷疑我的解決方案不夠理想。我在表A和表B之間有一對多的關係,TableB中的實體具有對錶A的引用。我有,我想同時刪除表A行的所有兒童的情況,我認爲這可以通過簡單地清除集合來實現:實體框架 - 清除子集合

Entity.Children.Clear() 

不幸的是,當我試圖挽救由此產生對外變化重點違規。

被添加的關係或 從AssociationSet 'FK_EntityB_EntityA' 刪除。對於基數 約束,還必須添加或刪除相應的「EntityB」 。

我想出的解決方案是通過實體上下文的DeleteObject()手動刪除對象,但我只知道我使用的邏輯是錯誤的。

while (collection.Any()) 
    Entities.DeleteObject(collection.First()); 

原因之一,事實上,我不得不使用WHERE()循環似乎遠低於理想,但我想這純粹是我的一個語義評估。無論如何,我是如何做錯的,或者是否有更好的方法來清除實體的子實體集合,以便實體框架在所有已刪除的對象上正確調用數據存儲刪除?

回答

20

Clear()參考刪除到實體,而不是實體本身。

如果你想這是總是相同的操作,你可以處理AssociationChanged

Entity.Children.AssociationChanged += 
    new CollectionChangeEventHandler(EntityChildrenChanged); 
Entity.Children.Clear();    

    private void EntityChildrenChanged(object sender, 
     CollectionChangeEventArgs e) 
    { 
     // Check for a related reference being removed. 
     if (e.Action == CollectionChangeAction.Remove) 
     { 
      Context.DeleteObject(e.Element); 
     } 
    } 

您可以使用部分類的實體建造這一點。

+0

這看起來很完美。從部分類中,是否有任何直接(或間接)的上下文路由? – 2010-01-13 17:29:48

+1

是的,有一個間接路線:http://blogs.msdn。com/alexj/archive/2009/06/08/tip-24-how-to-get-the-objectcontext-from-an-entity.aspx – 2010-01-13 17:49:33

+0

幾乎看起來我只是在構建while()循環刪除到我的存儲庫中,以便我可以輕鬆地重用它。我不必擔心解決上下文的問題,並且它適當靈活。儘管如此,我還沒有必要在C#中編寫while()循環很長一段時間,這感覺幾乎是錯誤的。 – 2010-01-13 17:52:27

5

您可以在父實體和子實體之間創建標識關係,並且在將父實體從集合中刪除時,EF將刪除子實體。

public class Parent 
    { 
     public int ParentId {get;set;} 
     public ICollection<Child> Children {get;set;} 
    } 

    public class Child 
    {   
     public int ChildId {get;set;} 
     public int ParentId {get;set;} 
    } 

映像配置:

modelBuilder.Entity<Child>().HasKey(x => new { x.ChildId, x.ParentId }); 
    modelBuilder.Entity<Parent>().HasMany(x => x.Children).WithRequired().HasForeignKey(x => x.ParentId); 
5

絕招:當設置了父母和孩子之間的關係,你必須創建孩子一個「複合」鍵。這樣,當您告訴父節點刪除1或其所有子節點時,實際上將從數據庫中刪除相關記錄。

要使用流利的API配置組合鍵:

modelBuilder.Entity<Child>().HasKey(t => new { t.ParentId, t.ChildId }); 

然後,刪除有關兒童:

var parent = _context.Parents.SingleOrDefault(p => p.ParentId == parentId); 

var childToRemove = parent.Children.First(); // Change the logic 
parent.Children.Remove(childToRemove); 

// you can delete all children if you want 
// parent.Children.Clear(); 

_context.SaveChanges(); 

完成!