2013-08-07 21 views
4

我有具有以下結構的Code First EF 5.0型號:爲什麼實體框架只能在集合中級聯單個項目?

public class Widget 
{ 
    public virtual Int32 Id { get; set; } 
    public virtual String Name { get; set; } 
} 

public class Product 
{ 
    public virtual Int32 Id { get; set; } 
    public virtual ICollection<Widget> Widgets { get; set; } 
    public virtual AddWidget(Widget widget) 
    { 
     Guard.NotNull(widget); 

     if (Widgets == null) 
     { 
      Widgets = new List<Widget>(); 
     } 

     Widgets.Add(widget); 
    } 
} 

當我嘗試保存新的瞬態Product一個以上的加Widget,只是添加的第一個Widget保存:

// ProductManagementContext is a DbContext 
// ProductManagementContext.Products is a DbSet<Product> 
using(var context = new ProductManagementContext()) 
{ 
    var product = new Product(); 
    product.AddWidget(new Widget() { Name = "Foo" }); 
    product.AddWidget(new Widget() { Name = "Bar" }); 
    context.Products.Add(product); 
    context.SaveChanges(); 
} 

此時,Widget表中只存在「Foo」。我使用SQL Server Profiler來檢查數據庫中的數據,並且只有一個INSERT語句針對添加了兩個的集合中的第一個Widget發佈。

爲什麼EF級聯兩個新實體?

+1

不知道這是相關的或沒有,但爲什麼在集合中的AddWidget()方法在產品構造初始化代替,? – etorrejon

+0

我很好奇這是什麼區別?從設計的角度來看,這是過度的初始化,但EF可能會有一些實用的原因來覆蓋設計決策,例如在構建後捕獲屬性狀態。即便如此,因爲我通過屬性訪問器改變了值,所以行爲應該沒有區別。 – codekaizen

+1

這是一個愚蠢的問題,但我會問它:你在所有的ID上都有'[DatabaseGenerated(DatabaseGeneratedOption.Identity)]'屬性,對吧? – dasblinkenlight

回答

0

我不太確定,但我認爲這是因爲ID中的虛擬關鍵字。

你說它的代碼是第一個,而db中的一個鍵表示一個不可變屬性。允許該參數被否決是混亂的,而且很可能不正確......

而且子元素的列表被定義爲跟隨this.Widgets = new HashSet<Widget>();至極是比較通用的一個列表...我給它一個鏡頭

Ps我首先使用了模型

1

您的問題不能用給出的代碼重現。我已經複製並粘貼了它,修復了編譯問題(AddWidget需要一個返回類型),刪除了對Guard的調用,運行它並看到兩個Widgets都出現在數據庫中。

這裏是完整的代碼。希望你能發現你的代碼不同。

using System; 
using System.Collections.Generic; 
using System.Data.Entity; 

namespace EF_SO_Q 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      using (var context = new ProductManagementContext()) 
      { 
       var product = new Product(); 
       product.AddWidget(new Widget() { Name = "Foo" }); 
       product.AddWidget(new Widget() { Name = "Bar" }); 
       context.Products.Add(product); 
       context.SaveChanges(); 
      } 
     } 
    } 

    public class Widget 
    { 
     public virtual Int32 Id { get; set; } 
     public virtual String Name { get; set; } 
    } 

    public class Product 
    { 
     public virtual Int32 Id { get; set; } 
     public virtual ICollection<Widget> Widgets { get; set; } 
     public virtual void AddWidget(Widget widget) 
     { 

      if (Widgets == null) 
      { 
       Widgets = new List<Widget>(); 
      } 

      Widgets.Add(widget); 
     } 
    } 

    public class ProductManagementContext : DbContext 
    { 
     public DbSet<Widget> Widgets { get; set; } 
     public DbSet<Product> Products { get; set; } 
    } 
}