为什么我的EF4.1关系在赋值为null时没有被设置为null?

6
在我的系统中,我有一些任务,这些任务可以选择分配给联系人。因此,在我的业务逻辑中,我有以下代码:
 if (_contactChanged) { task.Contact = contact; }

如果没有指定联系方式,contact变量将为null。提交更改时,这应该会将联系关系置为空,但我已经注意到99%的时间都没有发生这种情况(我看到过一次,但在反复检查此代码后没有保持一致性)。
当我进行调试时,我已经验证了_contactChangedtrue且内部代码没有被触发。但是,在我步过task.Contact = contact;之后,我注意到尽管contact为空,但task.Contact的类型为。
{System.Data.Entity.DynamicProxies
.Contact_4DF70AA1AA8A6A94E9377F65D7B1DD3A837851FD3442862716FA7E966FFCBAB9}

并且仍然与先前的数据绑定在一起。

为什么代理没有被设置为null,我该如何使其正常工作?


问题只会在调试代码时出现还是在普通执行中也会出现?你是否也定义了外键属性? - Ladislav Mrnka
它也会在常规代码执行中发生,我注意到这一点是因为关系没有被移除。外键已经正确定义。 - KallDrexx
我曾以为我疯了,认为这是模型绑定问题。然后我进行了调试,并发现了这个小的错误。非常奇怪,等于运算符必须重载为 DynamicProxies,并且它不能正确地处理 null 值。 - Khalid Abuhakmeh
1个回答

9

哇,好问题。我已经确认/重现了这个问题,即使参考对象不是动态代理。 t.Contact = null; 也不起作用!

到目前为止,我最好的答案是说:

    context.Entry(task).Reference(t => t.Contact).CurrentValue = null;

我真的希望有比这更好的方法,因为这是一些非常不方便的语法。

更新:

这个可以工作:

    var task = context.Tasks
        .Where(...your condition here...)
        .Include(t => t.Contact)
        .First();

    task.Contact = null;

或者,

如果您的模型中定义了一个外键ID(例如可空的ContactId),这将变得更加容易。


在开车回家的路上,我其实也有同样的想法,即由于延迟加载关系尚未加载,这是一个关系问题,并且我有与您更新相同的想法。明天早上会试一试! - KallDrexx
@KallDrexx - 听起来不错。现在我想,使用CurrentValue是否更可取。从性能的角度来看,它具有更少的数据库读取优势(无需JOIN)和上下文跟踪较少(没有实体加载)。使用SQL Profiler进行的一些初步测试支持这种说法中的数据库方面。 - anon
“CurrentValue” 不是一个好的解决方案,因为我必须对抽象 EF 的 UnitOfWork 对象进行一些修改。然而,你的第二个解决方案可行,我将 ContactId 设置为 null,似乎没有任何问题(而且不需要从数据库中额外加载数据)。 - KallDrexx
+1 表示 context.Entry(task).Reference(t => t.Contact).CurrentValue = null; - Sprintstar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接