2015-06-24 170 views
2

我不知道如果我這樣做的正確的方式或沒有,所以需要諮詢。實體框架 - 更新實體添加/修改的孩子和孫子實體

我有一個實體,這個實體有一個孩子集合,每個孩子實體有另一個孩子集合。像這樣(簡化的例子)的東西

public MyEntity() { 
    public long Id { get; set; } 
    public ICollection<MyChild> Children { get; set; } 
} 

public MyChild() { 
    public long Id { get; set; } 
    public long MyEntityId { get; set; } 
    public MyEntity MyEntity { get; set; } 
    public ICollection<MyGrandChild> Children { get; set; } 
} 

public MyGrandChild() { 
    public long Id { get; set; } 
    public long MyChildId { get; set; } 
    public MyChild MyChild { get; set; } 
    public string Name { get; set; } 
} 

現在在我們的應用中,用戶檢索從我們的WebAPI這個實體到angularJs應用。然後用戶更新實體(和子實體)並將實體傳遞迴webApi。我正在使用模型將對象從我的webApi傳遞到angularJs應用程序,它們看起來像這樣。

public MyEntityModel() { 
    public long Id { get; set; } 
    public ICollection<MyChildModel> Children { get; set; } 
} 

public MyChildModel() { 
    public long Id { get; set; } 
    public ICollection<MyGrandChildModel> Children { get; set; } 
} 

public MyGrandChildModel() { 
    public long Id { get; set; } 
    public string Name { get; set; } 
} 

一旦模型傳遞迴webApi,我使用Auto Mapper將它們轉換回實體對象。

現在我感到困惑的一點,我現在的對象傳遞給我的服務層,我的方法類似於這樣

public Task<int> UpdateAsync(MyEntity updated) { 
    _context.Entry(updated).State = EntityState.Modified; 

    return _context.SaveChangesAsync(); 
} 

如果我添加一個新MyChildMyGrandChild對象MyEntity myEntity所存在或之後更新MyChildMyGrandChild對象然後更改沒有提交到數據庫?我改變了我的UpdateAsync方法,但這真的需要嗎?

public Task<int> UpdateAsync(MyEntity updated) { 
    _context.Entry(updated).State = EntityState.Modified; 

    foreach (var child in updated.Children) { 
     if (child.Id == 0) { 
      _context.Entry(child).State = EntityState.Added; 
     } else { 
      _context.Entry(child).State = EntityState.Modified; 
     } 

     foreach (var grand in child.Children) { 
      if (grand.Id == 0) { 
       _context.Entry(grand).State = EntityState.Added; 
      } else { 
       _context.Entry(grand).State = EntityState.Modified; 
      } 
     } 
    } 

    return _context.SaveChangesAsync(); 
} 

難道我真的必須遍歷每個集合和子集合,檢查id是否等於0並相應地設置其狀態?

回答

1

是的,你必須這樣做。

當您在DbContext範圍內完成所有工作時,需要注意跟蹤實體中發生的變化,並且不必讓DbContext知道哪些變化。

但是,在多層應用程序中,當您移動層之間的實體時,它們不能保存在DbContext範圍內,因此您需要負責跟蹤cahnges。

朱莉勒曼建議實現接口跟蹤每個實體的狀態。該接口具有保持實體狀態的屬性。這在客戶端被修改,並在服務器上訪問以設置每個實體狀態:獲取服務器端的實體,將它們附加到上下文,並根據跟蹤接口屬性修改其狀態。 (我找不到參考資料,但它在她的編程實體框架書以及她的Pluralsight課程中都有介紹)。

Trackable Entities也可以是你的興趣。

如果你希望這種事情發生「自動地」,你可以使用Breeze。這使您可以使用JavaScript代碼輕鬆地在客戶端公開EF模型。此代碼能夠跟蹤客戶端的更改(並執行諸如驗證等許多其他操作),並將它們發送回服務器以更新數據庫。開始很容易。基本上你需要爲服務器安裝NuGet包來實現一個Breeze控制器,這是用很少的代碼行來完成的,還有爲客戶端實現的JavaScript代碼的NuGet包。建議使用一些MVVM JavaScript庫,如KnockoutAngularJS,因爲更改將通過訂閱這些庫創建的可觀察對象來自動跟蹤。

+1

我念叨breeze.js和有點糊塗,不微風讓您不必創建單獨的「型號」我angularJs應用和我的WebAPI之間傳遞?我創建了這些「模型」,因爲並非所有數據都需要傳遞。 breeze.js可以這樣工作,還是我爲自己做了更多的工作? – Gillardo

+0

使用微風是否消除了視圖模型的優點? – Hans

+0

它沒關係,我不能使用微風。我們的客戶可以從另一個應用程序調用我們的webApi,所以我將不得不在我的服務範圍內完成。我現在在我的IDbContext中添加了一個名爲Attach的基本函數,它執行可怕的IF檢查,並將實體狀態設置爲Modified或Added。 – Gillardo