I'm having trouble with detecting changes of a navigation property:
My testing model looks like this:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Address Address { get; set; }
}
public class Address
{
public int Id { get; set; }
public string Name { get; set; }
}
I've created and saved an object of type Person
with both Name
and Address
properties assigned. My problem is that if I fetch the Person
object back from the database and I change the Address
property (ex. to null) then EF doesn't detect the change!
My code is this:
using (var ctx = new EFContext())
{
Person p = ctx.People.First();
// p.Address IS NOT NULL!
p.Address = null;
var entry = ctx.Entry(p);
}
Why is entry.State
Unchanged
?
Edit: If I call SaveChanges
, the record is saved correctly (the Address
become null)!
Edit 2: I've created the foreign key property as billy suggested. If I inspect the Person
object in Visual Studio, the State
is Modified
. If I don't stop with the debugger inspecting the object's values, the state is Unchanged
!
Edit 3: Loading the Person
object using ctx.People.Include(x => x.Address).First();
solves the problem. Is there a way to avoid calling Include
and continue to modify the Address
property instead of the AddressId
one?
First of all: You MUST follow @billy's advice to use Include
. Your remark "p.Address IS NOT NULL!" is only true because you are watching p.Address
in the debugger and thereby triggering lazy loading in the debugger, so the change of setting the address to null
is detected. In release mode or when you don't inspect the properties in the debugger your code wouldn't work and no changes would be saved.
So, the answer to your Edit 3 is: No.
Second: var entry = ctx.Entry(p)
only returns entity states and you didn't change an entity state but instead a relationship state, or more precisely you deleted a relationship. You can't inspect relationship states with the DbContext
API but only with the ObjectContext
API:
Person p = ctx.People.Include(x => x.Address).First();
p.Address = null;
var objCtx = ((IObjectContextAdapter)ctx).ObjectContext;
var objentr = objCtx.ObjectStateManager.GetObjectStateEntries(EntityState.Deleted);
objentr
will have an entry of type RelationshipEntry
now:
EF will consider this relationship entry together with entity state entries when you call SaveChanges()
and delete the relationship, i.e. set the Address
foreign key column of the Person
in the database to NULL
.
About Edit 2: Changing a foreign key property (which is a scalar property in your model) is a change of the entity itself, so the entity state will be Modified
in this case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With