2011-08-08 63 views
1

我使用EF4.1代碼優先。我無法獲得一個非常簡單的插入來保存相關的實體ID。生成的SQL總是爲任何相關實體插入NULL。示例代碼如下。任何人都可以看到我在這裏做錯了嗎?它確實插入了非實體屬性,例如字符串。此外,我在數據庫初始化類中有類似的代碼來種子測試數據,它似乎工作正常。EF4.1代碼優先添加實體與相關實體

 using (var ctx = new DataContext()) 
     { 
      ctx.Users.Attach(existingUser); 

      // create item and add to context 
      var newItem = new MyItem(); 
      ctx.MyItems.Add(newItem); 

      // set related entity 
      newItem.CreatedBy = existingUser; 

      ctx.SaveChanges(); 
     } 

回答

1

您的代碼應該使用您的默認配置DbContext。一個可能的解釋是這是行不通的是,你必須自動變化檢測無效,例如,如果你在你的上下文的構造是這樣的:

public DataContext() 
{ 
    this.Configuration.AutoDetectChangesEnabled = false; 
} 

在這種情況下EF就無法檢測到導航屬性newItem.CreatedBy的變化在將新項目添加到上下文之後。 (如果變化檢測未禁用SaveChanges會檢測到這一最後的修改。)

你添加新的項目之前,上下文您可以更改代碼,以便設置導航屬性發生了:

using (var ctx = new DataContext()) 
{ 
    ctx.Users.Attach(existingUser); 

    // create item and add to context 
    var newItem = new MyItem(); 

    // set related entity 
    newItem.CreatedBy = existingUser; 

    ctx.MyItems.Add(newItem); 

    ctx.SaveChanges(); 
} 

這應該在沒有自動變化檢測的情況下工作。

+0

我的確將變化檢測設置爲false。如上所述移動代碼解決了這個問題。謝謝您的幫助。我認爲還必須有某種方法來標記該物業已更改?您更新現有實體的情況如何? –

+0

它看起來像這樣做:'ctx.Entry(existingItem).State = EntityState.Modified'是在附加現有實體的情況下的解決方案。 –

+0

@Barry:請注意,手動將狀態設置爲'Modified'會導致*完整*更新SQL語句:*所有*屬性都將發送到服務器,無論它們是否真正更改。從數據庫中檢索原始對象並將更改後的屬性合併到其中可能會更好(性能明智)。 EF將跟蹤這些更改並僅發送包含真正更改屬性的更新命令。 – Slauma

0

試試這個:

using (var ctx = new DataContext()) 
{ 
    ctx.Users.Attach(existingUser); 

    // create item and add to context 
    var newItem = new MyItem(); 
    ctx.MyItems.Add(newItem); 

    // set related entity 
    newItem.CreatedBy = existingUser; 

    // Added 
    ctx.ObjectStateManager.ChangeObjectState(newItem.CreatedBy, EntityState.Added); 

    ctx.SaveChanges(); 
} 

如果不工作,改變符合:

ctx.ObjectStateManager.ChangeObjectState(newItem.CreatedBy,EntityState.Modified);

添加了1行...希望它有幫助。