Entity Framework:代码中的外键优先
Entity Framework: Foreign Key in code first
我的代码有什么问题导致出现以下错误:
Unable to determine a valid ordering for dependent operations. Dependencies may exist due to foreign key constraints, model requirements, or store-generated values
代码:
Class食物:
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; }
}
Class 人:
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 }
});
}
看起来你有循环依赖。
答案 在这里:
- Unable to determine a valid ordering for dependent operations
- Unable to determine a valid ordering for dependent operations?
- Entity Framework Code First Circular Dependices
- Entity Framework 4: inheritance and Associations
- Entity Framework Circular Reference
- Code First Circular Reference Foreign Key Configuration
- How to configure a self referencing object in entity framework
可选改进:
您应该声明您的 navigation property as virtual!
如果您使用的是 C# 6.0 或更高版本,请更改您的 [ForeignKeyAttribute]
Data Annotation definition to [ForeignKey([nameof(BestFoodId))]
to avoid errors with hard coded property names. nameof
是一个非常酷的编译器功能! :)
错误原因:混淆的关联
发生这种情况是因为 Entity Framework 按照惯例假设 Person.BestFoodId
的 逆 属性 是 Food.Persons
。换句话说:Person.BestFood
和 Food.Persons
被假定为一对多关联的两端,具有 Person.BestFoodId
作为外键。
您可以通过向 BestFood
添加 [InverseProperty]
属性来验证:
public class Person
{
...
[ForeignKey("BestFoodId")]
[InverseProperty("Persons")]
public Food BestFood { get; set; }
...
}
这会导致同样的错误。
此错误 -- 没有有效的排序 -- 总是表示先有鸡还是先有蛋的问题。在您的情况下,EF 尝试插入食物,这些食物需要插入人的生成 ID 作为外键,而插入人需要插入的 foo2
食物的生成 ID。
解决方案:显式映射关联
实际上,Person
和Food
有两个关联:
- 1-n:
Food
可以是 BestFood
的 n 个人。
- n-m:n
Food
s可以是m个人的FavoriteFoods
在您的模型中,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 服务器限制)。
有了这个,EF 知道如何确定插入的有效顺序:它将首先插入食物,然后插入人(使用生成的 foo2
Id 作为外键),然后PersonFavoriteFood
table.
中的连接记录
我的代码有什么问题导致出现以下错误:
Unable to determine a valid ordering for dependent operations. Dependencies may exist due to foreign key constraints, model requirements, or store-generated values
代码:
Class食物:
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; }
}
Class 人:
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 }
});
}
看起来你有循环依赖。
答案 在这里:
- Unable to determine a valid ordering for dependent operations
- Unable to determine a valid ordering for dependent operations?
- Entity Framework Code First Circular Dependices
- Entity Framework 4: inheritance and Associations
- Entity Framework Circular Reference
- Code First Circular Reference Foreign Key Configuration
- How to configure a self referencing object in entity framework
可选改进:
您应该声明您的 navigation property as virtual!
如果您使用的是 C# 6.0 或更高版本,请更改您的
[ForeignKeyAttribute]
Data Annotation definition to[ForeignKey([nameof(BestFoodId))]
to avoid errors with hard coded property names.nameof
是一个非常酷的编译器功能! :)
错误原因:混淆的关联
发生这种情况是因为 Entity Framework 按照惯例假设 Person.BestFoodId
的 逆 属性 是 Food.Persons
。换句话说:Person.BestFood
和 Food.Persons
被假定为一对多关联的两端,具有 Person.BestFoodId
作为外键。
您可以通过向 BestFood
添加 [InverseProperty]
属性来验证:
public class Person
{
...
[ForeignKey("BestFoodId")]
[InverseProperty("Persons")]
public Food BestFood { get; set; }
...
}
这会导致同样的错误。
此错误 -- 没有有效的排序 -- 总是表示先有鸡还是先有蛋的问题。在您的情况下,EF 尝试插入食物,这些食物需要插入人的生成 ID 作为外键,而插入人需要插入的 foo2
食物的生成 ID。
解决方案:显式映射关联
实际上,Person
和Food
有两个关联:
- 1-n:
Food
可以是BestFood
的 n 个人。 - n-m:n
Food
s可以是m个人的FavoriteFoods
在您的模型中,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 服务器限制)。
有了这个,EF 知道如何确定插入的有效顺序:它将首先插入食物,然后插入人(使用生成的 foo2
Id 作为外键),然后PersonFavoriteFood
table.