C# 实体框架&x27;s AddOrUpdate导致不正确的外键更新

C# 实体框架&x27;s AddOrUpdate导致不正确的外键更新,c#,entity-framework,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 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; }
}
公共类国家
{
公共虚拟整数Id{get;set;}
[必需]
公共虚拟字符串名称{get;set;}
公共虚拟ICollection城市{get;set;}
}
公营城市
{
公共虚拟整数Id{get;set;}
[必需]
公共虚拟字符串名称{get;set;}
公共虚拟国家{get;set;}
公共虚拟int CountryId{get;set;}
}
类TestContext:DbContext
{
公共数据库集城市{get;set;}
公共数据库集国家{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();
        }
    }
}
静态类程序
{
静态void Main()
{
SetInitializer(新的DropCreateDatabaseIfModelChanges());
使用(var db=newtestcontext())
{
db.Database.Initialize(true);
db.Database.Log=Console.Write;
var country=db.Countries.Create();
country.Name=“法国”;
db.Countries.AddOrUpdate(a=>a.Name,country);
var city=db.Cities.Create();
city.Name=“巴黎”;
城市。国家=国家;
db.Cities.AddOrUpdate(q=>q.Name,city);
db.SaveChanges();
}
}
}
第一次运行时,一切正常,数据库中的CountryId字段设置正确。但是,当我第二次运行它时,
db.SaveChanges()
试图将Paris的CountryId设置为0,这违反了不可为空的外键约束

问题似乎是,尽管
城市
国家
是变更跟踪代理,但
国家ID
属性从未更新。不过,手动更新并没有帮助

这是预期的行为吗?如果是,我如何使用
AddOrUpdate
,而不进行这样的更改?通过设置外键来执行所有操作似乎不是一个选项,因为这些外键在代码第一次运行时不可用。

也许您需要这个

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

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

 city.Name = "Paris";
 city.Country = country;
在您的调查中,您使用导航属性

 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);
我没有测试它