【问题标题】:Foreign keys in Entity Framework not updating correctly实体框架中的外键未正确更新
【发布时间】:2012-04-16 10:34:16
【问题描述】:

我在实体框架中遇到外键关系问题。我有两张桌子:PersonsCountriesPersons 有一个指向 CountryId 的外键列。

由于Countries 表很少更改,我只想获取它的数据一次,处理DatabaseContext,并将Countries 的列表缓存在某处。这就是我遇到问题的地方。

实体框架似乎希望您打开数据库上下文,根据需要添加/编辑行,然后关闭数据库上下文。如果打开,获取数据,关闭;然后稍后打开,保存数据,关闭;有问题。

所以我的 POCO 对象如下所示:

public class Country {
    public int CountryId {get; set; }
    public String Name {get; set; }
}

public Person {
    public int PersonId {get; set; }
    public virtual Country Country {get; set; }
}

然后,我尝试像这样创建一个新人:

Country[] countries;
using (var dt = new DatabaseContext())
{
    countries= dt.Countries.ToArray();
}

Person person = new Person();
person.Country = countries[0];
using (var dt = new DatabaseContext()) { 
    dt.Entities.Add(person);
    dt.SaveChanges();
}

保存时,实体框架在Countries 表中创建一个与countries[0] 同名的新行,但新的递增ID。这显然不是预期的结果 - 该人应该将其 Country_CountryId 字段设置为 countries[0] 的 id,并且不应创建新行。

我该如何解决这个问题?我认为一种解决方案是强制实体框架在给定一个已经设置了主键的对象时创建一个新行。有没有办法做到这一点?

【问题讨论】:

    标签: c# entity-framework ef-code-first


    【解决方案1】:

    我想知道你是否至少在互联网上搜索一下,然后再花很大力气描述这个问题,因为这是每隔几天就会被问到的非常常见的问题。

    Add 方法在实体图中添加所有实体。因此,如果您将country 连接到person 并且country 未附加到当前上下文,则在person 上调用Add 会将personcountry 标记为要插入的新实体。如果您不想插入 country,则必须告诉 EF country 不是新实体:

    Person person = new Person();
    person.Country = countries[0];
    using (var dt = new DatabaseContext()) { 
        dt.Entities.Add(person);
        dt.Entry(person.Country).State = EntityState.Modified;
        dt.SaveChanges();
    }
    

    【讨论】:

    • 感谢您的回答,但此解决方案并不理想,因为它需要程序员为每个子实体设置EntityState.Modified - 我觉得这会导致问题,并破坏封装。有什么方法可以在Add 附加未跟踪对象的位置拦截它?
    • 此解决方案是正确且假定的方法。您将保留 EF 未加载的实体图,因此您必须告诉 EF 对关系进行了哪些更改。无法拦截Add 方法。它甚至不能被覆盖,因为它不是虚拟的。
    • 我认为这是一个相当大的问题 - 你的解决方案对我们的真实数据库没有好处,其中Person 包含对 5 个不同国家、某些类型、关系定义等的引用。为所有这些写EntityState.Modified 需要很多行代码,而且维护起来也很糟糕。但是,我想不出更好的解决方案。
    • 所以让它更加自动化。本书Programming DbContext 提供了创建自定义接口的分步指南,该接口将定义State 属性。通过在每个实体中实现此接口并在应用程序逻辑中使用State 属性,您将能够在覆盖SaveChanges 的一个循环中正确设置所有对象的状态。
    【解决方案2】:

    我通过在我的DatabaseContext 类中添加以下两种方法解决了这个问题:

    public void Add(object target)
    {
        this.Set(target.GetType()).Attach(target);
        this.Entry(target).State = System.Data.EntityState.Added;
    }
    
    public void Modify(object target)
    {
        this.Set(target.GetType()).Attach(target);
        this.Entry(target).State = System.Data.EntityState.Modified;
    }
    

    【讨论】:

    • 这太令人困惑了。出于某种原因,Add 方法有效,但 Modify 无效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多