问题描述
编辑这似乎发生在 any 在一个方向上引用另一个实体的实体属性上.换句话说,对于下面的示例,Bar
覆盖 Equality 的事实似乎无关紧要.
Edit
This seems to occur for any Entity property that references another entity in one direction. In other words, for the below example, the fact that Bar
overrides Equality appears to be irrelevant.
假设我有以下课程:
public class Foo
{
public int? Id { get; set; }
public virtual Bar { get; set; }
}
public class Bar : IEquatable<Bar>
{
public int Id { get; set; }
public override bool Equals(object obj)
{
var other = obj as Bar;
return Equals(other);
}
public bool Equals(Bar other)
{
if (object.Equals(other, null))
return false;
return this.Id == other.Id;
}
public static bool operator ==(Bar left, Bar right)
{
return object.Equals(left, right);
}
public static bool operator !=(Bar left, Bar right)
{
return !object.Equals(left, right);
}
public override int GetHashCode()
{
return Id.GetHashCode();
}
}
请注意,此处Bar"有意与Id"相等,因为它或多或少代表一个查找表 - 因此任何两个具有相同 Id 的对象引用都应始终被视为相同.
Note that here, "Bar" intentionally has "Id" equality, because it more or less represents a lookup table - so any two object references with the same Id should always be considered the same.
这是奇怪的部分,当我将 Foo.Bar
设置为另一个 Bar
实例时,一切正常 - 一切都按预期更新.
Here's the weird part, this all works fine when I set Foo.Bar
to another Bar
instance - everything updates as expected.
但是,如果 foo
在从 DbContext
中检索到现有的 Bar
时,我会这样做:
However, if foo
has an existing Bar
when it is retrieved from the DbContext
and I do:
foo.Bar = null
那么属性实际上并没有改变!
then the property doesn't actually change!
如果我这样做:
var throwAway = foo.Bar;
foo.Bar = null;
那么该属性将实际设置并保存为null.
Then the property will actually set and save as null.
由于 Foo.Bar
属性只是一个虚拟的、自动实现的属性,我只能得出结论,这与延迟加载和实体框架代理有关 - 但为什么会出现这种特殊情况导致问题,我不知道.
Since the Foo.Bar
property is simply a virtual, auto-implemented property, I can only conclude that this has something to do with lazy-loading and Entity Framework proxies - but why this particular scenario causes a problem, I have no idea.
为什么 Entity Framework 会有这种行为,我怎样才能让它真正可靠地设置 null
?
Why does Entity Framework behave this way, and how can I get it to actually set null
reliably?
推荐答案
作为一种解决方法,我发现缓解此问题的最简单方法是让 setter 在设置支持字段为空,例如
As a workaround, the easiest way I've found to mitigate this issue is to have the setter call the getter before setting the backing field to null, e.g.
public class Foo
{
public int? Id { get; set; }
private Bar _bar;
public virtual Bar
{
get { return _bar; }
set
{
var entityFrameworkHack = this.Bar; //ensure the proxy has loaded
_bar = value;
}
}
}
这样,无论其他代码是否实际加载了该属性,该属性都能正常工作,但代价是可能不需要的实体加载.
This way, the property works regardless of whether other code has actually loaded the property yet, at the cost of a potentially unneeded entity load.
这篇关于实体框架只会将相关实体属性设置为“null".如果我先拿到房产的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!