2016-12-03 55 views
0

考慮下面的過度簡化代碼:業績不佳的實體關係修復了自己,而不是等待實體框架SaveContext

public class Child 
{ 
    public virtual Parent Parent { get; set; } 
} 

public class Parent 
{ 
    public List<Child> Children { get; set; } 
} 

在我的消費者的代碼,我有:

parent.Children.Add(child); 

這沒有設置child.Parent,直到我調用db.SaveContext();

我看到這是一個問題,例如,在保存之前將同一對象的幾個操作鏈接起來。

我的問題是,我應該不是這樣:

class Child 
{ 
     public virtual Parent Parent { get; set; } 

     public void SetParent(Parent parent) { 
     if (this.Parent != null) { this.Parent.Children.Remove(this); } 

     parent.Children.Add(this); 
     this.Parent = parent; 
     } 
} 

請注意代碼片段僅僅是用於說明目的。

通常我的問題是,我應該自己處理關係修復,而不是依靠EF。

+0

你爲什麼要處理這個問題?你關心什麼? –

+0

我的擔心是,除非我'保存',對象不是在一個正確的狀態。依靠EF來解決混亂似乎是錯誤的。 –

+0

這不是一團糟。你只是不知道實體的ID。 如果我沒有記錯的話 - 例如使用ObjectContext(在dbContext之前)將所有內容拋出 - 引用導航屬性的其他方面,分配Ids(如果知道)等。 –

回答

0

爲了簡單起見,我會盡量避免那種需要你必須這樣做的鏈式操作,但我認爲如果你需要這樣做會有什麼問題。

一個建議:不要直接暴露Children收集您的Parent類,使其setter方法私有或保護,並添加方法來添加和刪除在ParentChildren元素。這是確保設置Child父項的邏輯始終在集合更改時執行的方法。

public class Parent 
{ 
    public List<Child> Children { get; protected set; } 

    public void AddChild(Child child) 
    { 
     Children.Add(child); 
     child.Parent = this; 
    } 

    public void RemoveChild(Child child) 
    { 
     Children.Remove(child); 
     child.Parent = null; 
    } 
} 
+0

謝謝,但是使'setter'非公開並不能保護從變化收集。另一方面,我們不能將IReadOnlyCollection作爲EF導航屬性。僵持。 –

+0

目標不是保護集合免受更改,而是確保在發生這些更改時執行所需的'child.Parent = newParent'。而且EF只能通過公共的getter來處理導航屬性。試試這個:'public virtual ICollection Children {get; } = new HashSet ();' – Diana

+0

在不保護「Children」屬性的情況下,使用AddChild和RemoveChild這兩種方法就像在草地中間放置一扇堅實的門。 –