更新导航属性或外键?

时间:2015-12-31 15:16:43

标签: c# .net entity-framework

我正在使用Entity Framework,我想更新一个导航属性。例如,我有一个Profile对象,它具有Gender的导航属性。我想更改Gender。我可以更新GenderID对象的Profile,这是外键,或者使用新的Gender对象初始化Gender;这样:

profile.GenderID = 2;

Profile.Gender = new Gender{ID=2, Name = "Female"};

我们假设我有一个像Languages这样的集合来代表一个1:n的关系。我是否有LanguageID或语言列表的列表?如何在不打击数据库的情况下更新列表?

如果我选择后者,是什么告诉实体框架提交更新或插入?它是主键吗?

1 个答案:

答案 0 :(得分:1)

您有以下选择:

<强> 1。更新父对象中的外键字段:

profile.GenderID = 2;

这具有更新模型中该字段的效果,然后在上下文上调用.SaveChanges();后,数据库将更新,对象上的导航属性也将更新。


<强> 2。将导航属性直接更新为已附加到上下文的EXISTING对象:

例如:

var femaleEntity = context.Genders.First(g=>g.Name == "Female");
profile.Gender = femaleEntity;

在这个实例中,导航属性会立即更新,但.GenderId对象上的profile字段不会更新,直到您调用context.SaveChanges();,然后EF会将新值写入GenderId数据库中的列,并更新.GenderId对象上的profile属性。


第3。使用NEW对象更新导航属性:

Profile.Gender = new Gender{ID=2, Name = "Female"};

此处EF将尝试将新的Gender行添加到ID为2且Name = female的数据库中。如果还没有“女性”,你几乎肯定只想这样做。数据库的Gender表中的行,如果Gender ID是数据库分配的标识,则在调用.SaveChanges()时将使用分配的值覆盖它。


忽略关于我们的对象何时被EF更新的细微之处,前两个选项大致相同*但第三个选项具有不同的行为。我们需要知道(或确定)是否需要链接到现有的Gender对象或向数据存储添加新对象。

完全相同的原则适用于你的1:许多关系:

profile.Languages = new List<Languages>
{
    new Language{Name = "Spanish"}
}

在languages表中创建一个新行,而:

var spanish = context.Languages.First(l=>l.Name == "Spanish");
profile.Languages = new List<Languages>
{
    spanish
}

找到名称为&#39;西班牙语&#39;的现有行。然后更新导航属性。

如果您有一个存储在变量中的语言ID列表,您希望使用相关的语言对象更新导航属性:

var languagesToAdd = context.Languages.Where(l=>languageIds.Contains(l.ID)).ToList();
profile.Languages = languagesToAdd;

*当然,如果您已经 已经在内存中附加了Gender对象,因为获取数据(例如,通过调用{{1}在我的例子中,(当然)需要另一次往返数据库。