[英]Entity Framework: Foreign Key in code first
我得到以下錯誤的代碼是什么錯誤:
無法確定相關操作的有效順序。 由於外鍵約束,模型要求或商店生成的值,可能存在依賴關系
碼:
類食品:
public class Food
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public short Id { get; set; }
//some Property
public string Name { get; set; }
public virtual ICollection<Person> Persons { get; set; }
}
班級人員:
public class Person
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
//some Property
public string FirstName { get; set; }
[ForeignKey("BestFoodId")]
public Food BestFood { get; set; }
public short BestFoodId { get; set; }
public virtual ICollection<Food> FavoriteFoods { get; set; }
}
播種方法:
protected override void Seed(MyContext context)
{
Food food1 = new Food() { Name = "foo1" };
Food food2 = new Food() { Name = "foo2" };
Food food3 = new Food() { Name = "foo3" };
context.Persons.AddOrUpdate(new Person()
{
FirstName = "Jack",
BestFood = food2,
FavoriteFoods = new List<Food>() { food1, food2, food3 }
});
}
發生這種情況是因為按照慣例,實體框架假定Person.BestFoodId
的逆屬性為Food.Persons
。 換句話說: Person.BestFood
和Food.Persons
被認為是一對多關聯的兩端,具有Person.BestFoodId
作為外鍵。
您可以通過向[InverseProperty]
添加[InverseProperty]
屬性來進行BestFood
:
public class Person
{
...
[ForeignKey("BestFoodId")]
[InverseProperty("Persons")]
public Food BestFood { get; set; }
...
}
這將導致相同的錯誤。
此錯誤-沒有有效的訂購-始終表示雞和蛋的問題。 在您的情況下,EF嘗試插入需要插入人生成的ID作為外鍵的食物,而插入人需要插入的foo2
食物的生成ID。
在現實中, Person
與Food
有兩個協會:
Food
可以是n人的BestFood
Food
。 Food
可以成為m人FavoriteFoods
的Food
。 在您的模型中, BestFood
沒有逆屬性,這可能是因為...
public virtual ICollection<Person> BestFoodOf { get; set; }
...但是這不是必需的,因為它丟失了,所以它掩蓋了EF如何推斷關聯。
您可以通過顯式映射關聯來解決此問題,例如在DbContext
子類的OnModelCreating
覆蓋中:
modelBuilder.Entity<Person>()
.HasRequired(p => p.BestFood)
.WithMany() // No inverse property
.HasForeignKey(p => p.BestFoodId)
//.WillCascadeOnDelete(false)
;
modelBuilder.Entity<Person>()
.HasMany(p => p.FavoriteFoods)
.WithMany(f => f.Persons)
.Map(m => m.MapLeftKey("PersonId")
.MapRightKey("FoodId")
.ToTable("PersonFavoriteFood"));
我已經注釋掉WillCascadeOnDelete(false)
。 您要么添加此行,要么添加...
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
...以防止出現多個級聯的刪除路徑(SQL Server的限制)。
將其放置在適當的位置后,EF知道如何確定插入的有效順序:它將首先插入食物,然后插入人(使用生成的foo2
Id作為外鍵),然后在PersonFavoriteFood
表中連接記錄。
看起來您具有循環依賴關系。
答案在這里:
可選改進:
如果使用的是C#6.0或更高版本,請將[ForeignKeyAttribute]
數據注釋定義更改為[ForeignKey([nameof(BestFoodId))]
以避免使用硬編碼的屬性名稱出錯。 nameof
是一個非常酷的編譯器功能! :)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.