Entity Framework 5 does not clear navigation property

I have this weird issue with Entity Framework 5, where I have a navigation property in one of my objects that I would like to set to null . But for some reason, the property only clears a second time when I call this property:

 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(); } 

The Vehicle class created by the Entity Framework is as follows:

 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; } } 

This code is not very addicted, and at runtime, the Entity Framework generates proxy classes for Vehicle and ParkingBay , but I can’t understand what is going on inside this ParkingBay property, which does not clear the property on the first call.

Between Vehicle and ParkingBay is the normal foreign key relationship in SQL Server. Nothing special here.

UPDATE

ParkingBay as follows:

 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; } } 

What's going on here? Can someone enlighten me what I'm doing wrong?

+7
c # entity-framework-5 entity-framework
source share
2 answers

After the query statement ( db.Vehicles.Single ... ), the property is null because you are not loading it. Assigning a different value to it does not cause a lazy load, so nothing changes here.

Only when the property is loaded, the assignment (any assignment that also replaces it with another object) will have an effect. If the property is not loaded, the change tracker does not track anything.

The property can be loaded by including it in the request

 db.Vehicles.Include(v => v.ParkingBay)... 

or by subsequently accessing it in code, for example

 var pb = vehicle.ParkingBay; // triggers lazy loading. 

or by checking it in the debugger (watch or quickview), which also launches lazy loading.

Include is the recommended approach if you intend to apply any changes to the navigation properties yourself.

As noted below, a more efficient way to clear the navigation reference property is to set the model to a primitive foreign key value and set it to null . In your case, will it be something like int? ParkingBayId int? ParkingBayId . This pattern is known as foreign key associations, unlike independent associations when only a reference property is present.

+7
source share

You really need to load the property before setting it to null . I agree with Hert Arnold's answer, I just wanted to add more alternatives for this:

 db.Entry(vehicle).Reference(c => c.ParkingBay).Load(); vehicle.ParkingBay = null; 

OR

 db.Entry(vehicle).Reference(v => v.ParkingBay).CurrentValue = null; 

MSDN Relationships and Navigation Properties

+1
source share

All Articles