EntityFramework的AddOrUpdate导致错误的外键更新

时间:2013-11-30 12:07:17

标签: c# entity-framework

假设我有许多国家/地区,每个国家都有多个城市。我可以使用以下模型来表示:

public class Country
{
    public virtual int Id { get; set; }
    [Required]
    public virtual string Name { get; set; }

    public virtual ICollection<City> Cities { get; set; }
}

public class City
{
    public virtual int Id { get; set; }
    [Required]
    public virtual string Name { get; set; }

    public virtual Country Country { get; set; }
    public virtual int CountryId { get; set; }
}

class TestContext : DbContext
{
    public DbSet<City> Cities { get; set; }
    public DbSet<Country> Countries { get; set; }
}

实体框架正确识别外键并生成表。

但是,如果我现在尝试播种一些测试数据:

static class Program
{
    static void Main()
    {
        Database.SetInitializer(new DropCreateDatabaseIfModelChanges<TestContext>());
        using (var db = new TestContext())
        {
            db.Database.Initialize(true);
            db.Database.Log = Console.Write;

            var country = db.Countries.Create();
            country.Name = "France";
            db.Countries.AddOrUpdate(a => a.Name, country);

            var city = db.Cities.Create();
            city.Name = "Paris";
            city.Country = country;
            db.Cities.AddOrUpdate(q => q.Name, city);

            db.SaveChanges();
        }
    }
}

第一次运行时,一切正常,数据库中的CountryId字段设置正确。但是,当我第二次运行它时,db.SaveChanges()会尝试将Paris的CountryId设置为0,这违反了不可为空的外键约束。

问题似乎是,尽管citycountry是更改跟踪代理,但CountryId属性永远不会更新。但是,手动更新它对此没有帮助。

这是预期的行为,如果是这样,我怎样才能使用AddOrUpdate而不改变这样?通过设置外键来完成所有操作似乎不是一个选项,因为在代码第一次运行时它们不可用。

2 个答案:

答案 0 :(得分:1)

AFAIK AddOrUpdate不支持导航属性。此外,当AddOrUpdate没有通过输入获取任何属性时,它将使用默认值属性保存它。

在你的煽动中你使用导航属性。

 city.Name = "Paris";
 city.Country = country;

AddOrUpdate由于缺乏支持导航属性,因此无法在内部分配city.CountryId=country.Id。因此,您的city.CountryId值变为0,这是int的默认值。

您应该自己分配外键。

 var city = db.Cities.Create();
 city.Name = "Paris";
 city.Country = country;
 db.Cities.AddOrUpdate(q => q.Name, city);

应该是这样的

 var city = db.Cities.Create();
 city.Name = "Paris";
 city.Country = country;
 //Assign foreign key by manually.
 city.CountryId = country.Id;
 db.Cities.AddOrUpdate(q => q.Name, city);

我没有测试过。

答案 1 :(得分:0)

也许你需要这个......

[Key]
public virtual int Id { get; set; }