EF - 使用链接的现有实体保存新实体,从而创建重复项

时间:2011-07-20 03:04:35

标签: entity-framework-4.1 ef-code-first code-first

public class Car {
    public string SomeProperty { get; set; }
    public Manufacturer Manufacturer { get; set; }
    public IList<Color> Colors { get; set; }
}

public class Manufacturer { 
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Color { 
    public int Id { get; set; }
    public string Name { get; set; }
}

我已经摆满了颜色和制造商的桌子。当我创建一辆新车时,我希望能够从.net MVC中为它分配一个颜色和制造商。

当我用

保存我的新车时
context.Cars.Add(car);

创建了一个新的Car(很棒),但是也会创建一个新的Color和Manufacturer,即使这些对象已经设置了与数据库中的内容匹配的Id和Name。

我看到的两个解决方案是为汽车编写自定义保存方法,并告诉上下文制造商和颜色不变。

context.Cars.Add(car);
context.Entry(car.Manufacturer).State = EntityState.Unchanged;
foreach (Color color in car.Colors)
   context.Entry(car.Color).State = EntityState.Unchanged;

或者,从EF加载制造商和颜色,然后将它们链接到Car,而不是使用MVC绑定对象。

car.Manufacturer = carRepository.GetManufacturer(car.Manufacturer.Id);
car.Colors = carRepository.GetColorsById(car.Colors);

我对这两个解决方案都不感到兴奋,因为这个例子非常简单,但我的实际案例要复杂得多。我真的不想为我保存的每个对象详细说明EF。我有很多复杂的对象图来保存,这看起来很容易出错。

有没有办法让EF的行为更像NHibernate,你可以给它一些已经分配了ID的东西,它会在没有你干预的情况下假设它已经存在?

编辑 - 澄清问题以显示现有实体的集合以及多对一关系。

2 个答案:

答案 0 :(得分:1)

不幸的是,EF在NHibernate中没有类似session.Load的内容,允许你从id获取代理。

在EF中处理此问题的常用方法是创建一个单独的FK字段,其中包含与引用对应的标量值。例如:

public virtual Manufacturer Manufacturer { get; set; }
public int ManufacturerId { get; set; }

然后您只需设置ManufacturerId即可正确保存。

(“POCO”和“代码优先”这么多.Pffffff)

答案 1 :(得分:0)

您可以在实体中定义标量属性,并将值绑定到它们。例如,添加 ManufacturerIdColorId

public class Car {
    public string SomeProperty { get; set; }
    public int? ManufacturerId { get; set; }
    public virtual Manufacturer Manufacturer { get; set; }
    public int? ColorId { get; set; }
    public virtual Color Color { get; set; }
}

然后在分配时设置这些标量属性(例如通过DropDownList)

通过这种方式,您可以避免加载许多相关实体来填充实体。