我有一个File
实体和一个User
实体。 File
实体通过名为User
的属性与LastChangeUser
实体具有1:1的关系(这记录了上次更改文件的用户)。名为File
的{{1}}实体中还有一个字段,它是实际的FK关系。关系是单向的:LastChangeUserId
实体没有导航属性返回User
实体。
File
更改class File
{
public int Id { get; set; }
public int? LastChangeUserId { get; set; }
public virtual User LastChangeUser { get; set; }
}
class User
{
public int Id { get; set; }
}
后,我需要为File
设置LastChangeUser
。我只有用户的ID,而不是完整的User对象。所以,我这样做:
File
当新创建file.LastChangeUser = null;
file.LastChangeUserId = userId;
对象(然后将POCO添加到实体集合中)时,这似乎可以用于创建文件。
但是,当File
对象是从DB检索(作为代理)的现有对象时,它在更新文件时不起作用。
在后一种情况下,我在File
字段的数据库中最终得到NULL。 (调用SaveChanges后,对象在LastChangeUserId
和null
字段中都有LastChangeUser
。
也许我在这里做错了什么?什么是正确的方法?我是否真的需要获取LastChangeUserId
对象才能设置User
属性?
答案 0 :(得分:1)
@kevin_fitz解决方案在这里工作的原因是由于EF工作中的转换和验证方式。 EF中更改跟踪的默认行为是一种称为快照跟踪的方法,它基本上克隆了每个实体首次加载时的初始状态。当您保存EF中的更改时,会将每个实体的原始快照与当前状态对象(您正在修改的对象)进行比较,并且任何差异都会持久保存到数据库中。
此外,EF还对实体执行预提交验证(可以禁用FYI)。
在您的情况下,您对模型进行了两处更改,快照跟踪器将在保存时检测到这些更改(实际上它们之间存在冲突)。然而,跟踪器将尝试通过验证规则处理这两者,这将验证这是必需的关系并且不能设置为空。这就是为什么您看到此错误以及为什么删除null更新可以解决您的问题。
在旁注中,您实际上只需要更新导航属性上的对象或键以触发要更新的数据库关系。有关导航属性如何在EF codefirst checkout中工作的更多详细信息,请参阅我的文章:http://blog.staticvoid.co.nz/2012/07/entity-framework-navigation-property.html