2013-06-03 164 views
3

是否將父實體再次附加到上下文並更新它應該更新子實體?我錯過了什麼嗎?更新父實體不更新子實體

或者我是否應該爲子實體編寫更新EF邏輯(在DAL中)?

這是我的示例代碼模型:

ChildEntity entityChild; 
if (ParentEntity.ChildEntity.SingleOrDefault() != null) 
    entityChild = ParentEntity.ChildEntity.SingleOrDefault(); 
else 
{ 
    entityChild = new ChildEntity(); 
    ParentEntity.ChildEntity.Add(entityChild); 
} 

entityChild.ColumnA= txtA.Text; 
entityChild.ColumnB= txtB.Text; 

// Send entityParent for update 
_objParent.Update(entityParent) 

_objParent.Update()代碼:

context.vouchers.Attach(entityParent); 
ObjectStateEntry objectState = context.ObjectStateManager.GetObjectStateEntry(entityParent); 
objectState.ChangeState(System.Data.EntityState.Modified); 
context.SaveChanges(); 

UPDATE(父加載代碼示例)

public ParentEntity GetById(int id) 
    { 
     using (var context = new DBEntities()) 
     { 
      ParentEntity _entity = context.ParentEntity 
       .Include("ChildEntity") 
       .Where(e => e.parent_id == id); 

      return (ParentEntity)_entity.SingleOrDefault() 
     } 
    } 
+0

您要新增或更新的父對象?如果你正在更新對象,請告訴我們你是如何加載它的。 –

+0

請參閱上面已提供的_objParent.Update()代碼。 1)附加實體,2)獲取ObjectStateEntry,3)修改狀態,4)將更改保存到上下文中。 –

+0

你如何加載父項? –

回答

1

EF只跟蹤從瞭解對象的位置開始的變化。在EF中使用更新的最簡單方法是從DB加載現有對象,更新它並將其保存回來。在這種情況下,這意味着您應該從DB加載ParentEntity對象。

另一種方法是像你一樣使用Attach。在這種情況下,您應該首先呼叫附加不變ParentEntity然後致電ParentEntity.ChildEntity.Add(entityChild)

另一種方法是直接明確地添加新ChildEntity到的DbContext,那麼你可以在ChildEntity的外鍵值簡單地設置爲ParentEntity的核心價值,使它們相連。

+0

我明白了你的觀點。我唯一不清楚的問題是確定是添加ChildEntity還是修改?隨着ParentEntity在UI層中獲取更改(添加/修改ChildEntity),我必須設計一些技術來識別更改模式(添加/修改)。使用ChildEntity的ModifiedBy和EnteredBy屬性來識別chage模式是否合適? (即如果ModifiedBy爲null,則表示這應該是一個Add操作) –

+0

使用變更跟蹤最簡單的方法是在查詢中加載'ParentEntity'和所有相關的'ChildEntities'(使用'Include(p => ChildEntities)') ),然後在執行SaveChanges之前更新/添加子項。在EF中保存而不加載通常比預期的更困難。 –

1

您應該加載和更新使用語句中的實體 - 這樣所有的變化將通過實體框架追蹤:

using (var context = new DBEntities()) 
{ 
    // load and update entities 
    // .... 

    context.SaveChanges(); 
} 

UPDATE - 這只是一個例子,我會繼續它很簡單。我想創建一個服務,我願意把我的邏輯 - 這樣的事情:

public class ParentService 
{ 
    // other service methods here 

    protected DBEntities CreateContext() 
    { 
     return new DBEntities(); 
    } 

    public ParentEntity Update(int id, string columnA, string columnB) 
    { 
     ParentEntity _entity = null; 

     using (var context = CreateContext()) 
     { 
      bool isNew = false; 

      _entity = context.ParentEntity 
       .Include("ChildEntity") 
       .SingleOrDefault(e => e.parent_id == id); 

      ChildEntity entityChild = ParentEntity.ChildEntity.SingleOrDefault(); 

      if(entityChild == null) 
      { 
       entityChild = new ChildEntity(); 
       isNew = true; 
      } 

      entityChild.ColumnA = columnA; 
      entityChild.ColumnB = columnB; 

      if(isNew) 
      { 
       ParentEntity.ChildEntity.Add(entityChild); 
      } 

      context.SaveChanges(); 
     } 

     return _entity; 
    } 
} 

在UI代碼:

string id = .....; 
string columnA= txtA.Text; 
strign columnB = txtB.Text; 

var service = new ParentService(); 
ParentEntity parent = service.Update(id, columnA, columnB); 
+0

但問題是,實體通過應用程序層(DAL,BAL,UI)傳遞,因此與上下文分離。因此,您提供的樣本需要在這方面進行大量更改。不是嗎? –

+0

@ Ali.NET:更新了我的答案。我的建議是:創建一個包含所有邏輯和數據訪問的服務層。用戶界面將訪問該服務,這樣你就不會混淆UI和其他服務。 –

+0

我在腦海裏有這個邏輯。但是這種方式應用程序會打兩次服務器來更新實體。性能問題。 –