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的东西,它会在没有你干预的情况下假设它已经存在?
编辑 - 澄清问题以显示现有实体的集合以及多对一关系。
答案 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)
您可以在实体中定义标量属性,并将值绑定到它们。例如,添加
ManufacturerId
和ColorId
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)
通过这种方式,您可以避免加载许多相关实体来填充实体。