2013-08-07 18 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; } 
    } 
}