实体框架不会检测导航属性的变化 [英] Entity Framework won't detect changes of navigation properties
问题描述
我的测试模型如下所示:
public class Person
{
public int Id {get;组; }
public string Name {get;组; }
public virtual Address Address {get;组;
}
public class Address
{
public int Id {get;组; }
public string Name {get;组;
}
我创建并保存了一个Person类型的对象,名称和分配地址属性。我的问题是,如果我从数据库中取回该Person对象,并且更改了Address属性(例如:Null),那么e.f.没有检测到变化!
我的代码是这样的:
using(var ctx = new EFContext())
{
Person p = ctx.People.First();
//p.Address IS NOT NULL!
p.Address = null;
var entry = ctx.Entry(p);
}
为什么是 entry.State
不变?
编辑:如果我调用SaveChanges,记录将被正确保存null)!
编辑2:我创建的外键属性是比利建议的,如果我在visual studio中检查Person对象状态被修改..如果我不停止调试器检查对象的值状态是不变的!
编辑3:加载Person对象使用ctx.People.Include(x => x.Address).First();解决问题。有没有办法避免调用Include并继续修改Address属性而不是AddressId?
首先:您必须按照@ billy的建议,使用 Include
。您的评论 p.Address IS NOT NULL!仅适用于您调试器中的 p.Address
,从而触发延迟加载调试器,因此检测到将地址设置为 null
的更改。在释放模式下,或者当您不检查调试器中的属性时,您的代码将无法正常工作,并且不会保存更改。
所以,您的编辑的答案3是:否
第二: var entry = ctx.Entry(p)
只返回实体状态,您没有更改实体状态,而是更改关系状态,或者更准确地说,您删除关系。您不能使用 DbContext
API检查关系状态,但只能使用 ObjectContext
API:
Person p = ctx.People.Include(x => x.Address).First();
p.Address = null;
var objCtx =((IObjectContextAdapter)ctx).ObjectContext;
var object_
objentr
将有一个类型为 RelationshipEntry
now:
当您调用 SaveChanges()
并删除关系,即将数据库中 Person
的地址
外键列设置为 NULL
。
关于编辑2:更改外键属性(模型中的标量属性)实体本身的变化,所以在这种情况下,实体状态将为修改
。
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 the e.f. 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 the SaveChanges, the record is saved correctly (the Address become null)!
Edit 2: I've created the foreign key property as billy suggested and 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.
这篇关于实体框架不会检测导航属性的变化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!