假设我有多个国家,每个国家都有多个城市。我可以使用以下模型来表示:
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; }
}
Entity Framework 正确识别外键并生成表。
但是,如果我现在尝试播种一些测试数据:
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()
尝试将巴黎的 CountryId 设置为 0,这违反了不可为空的外键约束。
问题似乎是尽管 city
和 country
是更改跟踪代理,但 CountryId
属性永远不会更新。不过,手动更新它并没有帮助。
这是预期的行为吗?如果是,我如何使用 AddOrUpdate
而不像这样更改?通过设置外键来完成所有事情似乎不是一种选择,因为这些在代码第一次运行时不可用。
最佳答案
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);
我没有测试过。
关于c# - EntityFramework 的 AddOrUpdate 导致外键更新不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20300035/