2012-03-16 30 views
0

實體:EF:設置實體複雜字段設置爲null

public class Page 
{ 
    //... 
    public virtual Page Parent { get; set; } 
} 

需要設置父字段爲空。嘗試這樣做,但沒有運氣:

// Existing entity 
Page pageAttached = db.Pages.First(x => x.Id == page.Id); 
db.Entry(pageAttached).CurrentValues.SetValues(page); 
if (model.ParentId != null) 
    pageAttached.Parent = db.Pages.First(x => x.Id == model.ParentId); 
else 
    pageAttached.Parent = null; //does nothing 
db.SaveChanges(); 

回答

2

Parent不是「複雜的領域」,這是一個「導航屬性」。

如果你這樣做會工作嗎?

// Existing entity 
Page pageAttached = db.Pages.Include(x => x.Parent).First(x => x.Id == page.Id); 
db.Entry(pageAttached).CurrentValues.SetValues(page); 
if (model.ParentId != null) 
    pageAttached.Parent = db.Pages.First(x => x.Id == model.ParentId); 
else 
    pageAttached.Parent = null; //does nothing 
db.SaveChanges(); 

迴應置評1

不,我的意思.Include(x => x.Parent)。我更喜歡使用lambda超載進行強類型化。使代碼中的魔術串保持不變。

這樣做的原因是因爲DbContext使用動態生成的代理類進行延遲加載。當您只查詢.First(x => x.Id == page.Id)時,返回的對象實際上是一個實現您的Page實體作爲其基類的類。 (這就是爲什麼集合和導航屬性必須標記爲virtual,因此它們可以在動態代理中被覆蓋。)此外,即使在db中有父項,動態生成的代理也會有一個空的父引用。

直到父屬性get方法被調用,EF命中db才懶惰地加載父對象。這是當它發現數據庫實際上是否有一個null或非空的父屬性。所以,如果在父實際加載之前設置.Parent = null,那麼EF不會執行任何操作,因爲它已經爲空。

我建議的代碼使用.Include急切加載 Parent屬性。這意味着數據庫在單個數據庫調用中同時獲取子項+其父項。現在,當您設置null時,DbContext將跟蹤更改並在您的下一次SaveChanges中刪除關係。

+0

我想你的意思是'Page pageAttached = db.Pages.Include(「Parent」)。First(x => x.Id == page.Id);'它工作。你能解釋嗎? – Wonder 2012-03-17 08:19:35