实体框架5不清除导航属性

Ste*_*ven 7 .net c# ado.net entity-framework entity-framework-5

我在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();
}
Run Code Online (Sandbox Code Playgroud)

VehicleEntity Framework生成的类如下所示:

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; }
}
Run Code Online (Sandbox Code Playgroud)

这段代码是不是很退出,并在运行时的实体框架两者产生代理类VehicleParkingBay,但我不明白里面发生了什么ParkingBay失败清除在第一次通话的财产一样.

Vehicle和之间ParkingBay是和SQL Server中的正常外键关系.这里没什么特别的.

UPDATE

ParkingBay如下所示:

public partial class ParkingBay
{
    public ParkingBay()
    {
        this.Vehicles = new HashSet<Vehicle>();
    }

    public int Id { get; set; }
    public System.DateTime CreatedOn { get; set; }
    public int CreatedBy { get; set; }

    public virtual ICollection<Vehicle> Vehicles { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?有人可以告诉我我做错了什么吗?

Ger*_*old 7

在查询语句(db.Vehicles.Single ...)之后,属性 null,因为您没有加载它.为其分配另一个值不会触发延迟加载,因此此处没有任何更改.

只有在实际加载属性时,任务(任何赋值,也将其替换为另一个对象)才会生效.如果未加载该属性,则更改跟踪器无需跟踪.

可以通过将其包含在查询中来加载该属性

db.Vehicles.Include(v => v.ParkingBay)...
Run Code Online (Sandbox Code Playgroud)

或者通过在代码中稍后解决它,例如

var pb = vehicle.ParkingBay; // triggers lazy loading.
Run Code Online (Sandbox Code Playgroud)

或者在调试器(watch或quickview)中检查它,这也会触发延迟加载.

Include 如果您打算对导航属性本身应用任何更改,建议使用此方法.

如下所述,清除引用导航属性的更好的方法是在模型中公开原始外键值并将其设置为null.在你的情况下,这将是类似的int? ParkingBayId.当仅存在引用属性时,该模式被称为外键关联,而不是独立关联.

  • @Steven,你是对的,但问题仍然存在于.NET4.5/EF6中.为什么MS明确表示它应该在EF5 +中不起作用?... (3认同)