简体   繁体   English

如何在EF中使用外键正确更新实体?

[英]How do I correctly update an entity with foreign key in EF?

I went through this answer , but it still gave me the same exception. 我经历了这个答案 ,但仍然给了我同样的例外。 My DbContext has Configuration.AudoDetectChangesEnabled = false and Configuration.LazyLoadingEnabled = true , in case that makes a difference. 我的DbContext具有Configuration.AudoDetectChangesEnabled = falseConfiguration.LazyLoadingEnabled = true ,以防有所不同。 For a simple example, consider the following: 对于一个简单的示例,请考虑以下内容:

public class Employee {
    public int Id {get;set;}
    public int TitleId {get;set;}

    [ForeignKey(nameof(Employee.TitleId))]
    public virtual Title Title{get;set;}
}

Query is done with Context.Set<Employee>().Include(nameof(Employee.Title)) . 使用Context.Set<Employee>().Include(nameof(Employee.Title)) In my case, I have an existing Employee with an existing Title . 在我的情况下,我有一个现有的Employee和一个Title I've updated my entity with a new TitleId , one that already exists in the database. 我已经使用新的TitleId更新了我的实体,该TitleId已经存在于数据库中。 Then, I update the EntityState to EntityState.Modified and call SaveChanges() . 然后,我将EntityState更新为EntityState.Modified并调用SaveChanges() This gives the following Exception : 这给出了以下Exception

A referential integrity constraint violation occurred: The property value(s) of 'Employee.TitleId' on one end of a relationship do not match the property value(s) of 'Title.Id' on the other end.

Okay, so that should be due to a mismatch between the foreign key id and the navigation property. 好的,那应该是由于外键ID与Navigation属性之间的不匹配。 So then I set Title to null prior to setting EntityState . 因此,在设置EntityState之前,我将Title设置为null Still the same issue. 还是一样的问题。

Next, I've tried detaching the entity prior to setting EntityState.Modified . 接下来,我尝试在设置EntityState.Modified之前分离实体。 Now, saving the entity works, but when I try to load it again, I get a NullReferenceException on the navigation property. 现在,保存该实体即可,但是当我尝试再次加载它时,在导航属性上得到了NullReferenceException

What's the proper way to do this? 正确的方法是什么?

Do not try to update only the Id property, update the Title entity on the employee instead and the Id property should follow. 不要尝试仅更新Id属性,而是更新员工上的Title实体,然后应遵循Id属性。 So fetch the existing title and student from the db and set the title of the student to the title you fetched from the db. 因此,从数据库中获取现有的标题和学生,然后将学生的标题设置为您从数据库中获取的标题。

Other things i would do differently is using System.Data.Entity and use include with a lambda expression instead to make it more explicit and failsafe. 我会做其他改变的其他事情是使用System.Data.Entity,并使用带有lambda表达式的include来使其更加明确和故障安全。 Like so: 像这样:

 Context.Set<Employee>().Include(x => x.Title);

And if i read things right your ForeignKey annotation is obsolote in this case since EF conventions will map to the same name anyway. 如果我没看错,在这种情况下,因为EF约定始终会映射到相同的名称,所以您的ForeignKey注释已过时。 I also think it is a bit of a code smell to have mapping information on the entity. 我还认为在实体上具有映射信息有点代码味道。 Use fluent api instead. 请改用流利的api。 http://www.entityframeworktutorial.net/code-first/foreignkey-dataannotations-attribute-in-code-first.aspx http://www.entityframeworktutorial.net/code-first/foreignkey-dataannotations-attribute-in-code-first.aspx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM