After the query statement (db.Vehicles.Single ...
) the property is null, because you don't load it. Assigning another value to it doesn't trigger a lazy load, so nothing changes here.
Only when the property is actually loaded an assignment (any assignment, also replacing it by another object) will have an effect. If the property isn't loaded, the change tracker has nothing to track.
The property can get loaded by including it in the query
db.Vehicles.Include(v => v.ParkingBay)...
or by addressing it later in the code, e.g.
var pb = vehicle.ParkingBay; // triggers lazy loading.
or by inspecting it in the debugger (watch or quickview), which also trigger lazy loading.
Include
is the recommended approach if you intend to apply any changes to navigation properties themselves.
As commented below, a better performing way to clear a reference navigation property is to expose the primitive foreign key value in the model and set it to null
. In your case, this would be something like int? ParkingBayId
. This pattern is know as foreign key associations, as opposed to independent associations, when only the reference property is present.