我在Entity Framework 5中遇到了这个奇怪的问题,我在我的一个实体中有一个导航属性,我想将其设置为null
。但由于某种原因,我第二次调用此属性时,属性才会被清除:
using (var db = new Entities())
{
var vehicle = db.Vehicles.Single(v => v.Id == vehicleId);
// After this call, ParkingBay is still set.
vehicle.ParkingBay = null;
// Only after this call, ParkingBay becomes null.
vehicle.ParkingBay = null;
db.SaveChanges();
}
Entity Framework生成的Vehicle
类如下所示:
public partial class Vehicle
{
public int Id { get; set; }
public System.DateTime CreatedOn { get; set; }
public int CreatedBy { get; set; }
public virtual ParkingBay ParkingBay { get; set; }
}
此代码并不存在,并且在运行时,Entity Framework会为Vehicle
和ParkingBay
生成代理类,但我无法理解{{1}内部发生的情况在第一次调用时无法清除属性的属性。
ParkingBay
和Vehicle
之间是SQL Server中的正常外键关系。这里没什么特别的。
更新
ParkingBay
看起来像这样:
ParkingBay
这里发生了什么?有人可以告诉我我做错了吗?
答案 0 :(得分:7)
在查询语句(db.Vehicles.Single ...
)之后,属性 为null,因为您没有加载它。为其分配另一个值并不会触发延迟加载,因此此处没有任何更改。
只有在实际加载属性时,赋值(任何赋值,也将其替换为另一个对象)才会生效。如果未加载该属性,则更改跟踪器无需跟踪。
可以通过将属性包含在查询中来加载属性
db.Vehicles.Include(v => v.ParkingBay)...
或稍后在代码中解决,例如
var pb = vehicle.ParkingBay; // triggers lazy loading.
或在调试器(watch或quickview)中检查它,这也会触发延迟加载。
如果您打算对导航属性本身应用任何更改, Include
是推荐的方法。
如下所述,清除引用导航属性的更好的方法是在模型中公开原始外键值并将其设置为null
。在您的情况下,这将类似于int? ParkingBayId
。当只有引用属性存在时,此模式称为外键关联,而不是独立关联。
答案 1 :(得分:1)
在将属性设置为null
之前,您实际需要加载属性。我同意Gerd Arnold的回答,只是想添加更多替代方案来做到这一点:
db.Entry(vehicle).Reference(c => c.ParkingBay).Load();
vehicle.ParkingBay = null;
OR
db.Entry(vehicle).Reference(v => v.ParkingBay).CurrentValue = null;