添加复杂项时 EF6 主键冲突
EF6 Primary Key Violation When adding Complex Item
我有一个 classes 的实体集,其中有一个食谱;该配方可以有多个成分(用外键处理),每个成分可以有一个组件。有几组 table 遵循与此类似的模式,其中有几层
当我添加一个配方时,其中包含一些最终导致相同组件的成分,我收到一条错误消息,指出将配方添加到数据库会导致组件发生主键冲突 table .有没有办法告诉实体,如果一个组件具有相同的主键值,它应该更新而不是插入?我知道您可以使用 context.Recipes.AddOrUpdate(recipe)
在顶层执行此操作,但我如何才能在树结构中的每个子级别实现它?
以下是我已有的实体 classes 的一些总结示例:
public partial class Recipe
{
public int Id { get; set; }
public virtual ICollection<Ingredient> Ingredients { get; set; }
}
public partial class Ingredient
{
public int Id {get;set;}
public int ComponentId { get; set; }
public virtual Component Component { get; set; }
public virtual ICollection<Recipe> Recipes { get; set; }
}
public partial class Component
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
public string Description { get; set; }
public virtual ICollection<Ingredient> Ingredients { get; set; }
}
//在:DbContext class中,有这个:
modelBuilder.Entity<Ingredient>()
.HasMany(e => e.Recipes)
.WithMany(e => e.Ingredients)
.Map(m => m.ToTable("Recipe_Ingredient_Link").MapLeftKey("IngredientId").MapRightKey("RecipeId"));
我收到此错误消息是因为具有相同 Id 的两个组件具有不同的 Ingredients
ICollections 与之关联,导致 Entity 将它们视为不同的对象吗?如果是这样,我该如何解决这个问题?如果不是,是什么问题?
我从现有数据库生成 classes,除了关闭延迟加载外,没有更改它为我创建的代码。
我认为您的问题在于,在从 JSON 到 C# 对象的转换中,您为 JSON 中的每个组件获得了一个单独的对象。这意味着即使两个组件具有相同的 ID,它也是两个不同的对象,就像您也描述的那样。如图所示:
Recipe #1
|
|-- Ingr. #1
| |-- Comp. #1
|
|-- Ingr. #2
| |-- Comp. #2
|
|-- Ingr. #3
|-- Comp. #1 // Same ID as the one for Ingr. 1, but it's a separate C# object
当您尝试添加对象层次结构(通过仅添加 top-level Recipe
)时,Entity Framework 会将每个 C# 对象视为一个单独的实体。因此,即使两个对象共享相同的 ID,也没有逻辑告诉 EF 如何处理它。 IE。如果其他属性(除了 ID)不同,它应该如何表现?
所以我认为您需要做的是确保没有两个对象具有冲突的 ID。您必须遍历对象并确保如果两个组件具有相同的 ID,则需要删除其中一个组件并将 Ingredient
s link 指向同一个 Component
对象,如图所示:
Recipe #1
|
|-- Ingr. #1
| |----------------|
| |
|-- Ingr. #2 |
| |-- Comp. #2 |-- Comp. #1 // Now they point to the same C# object
| |
|-- Ingr. #3 |
|----------------|
我会让你考虑如何编写代码。
我有一个 classes 的实体集,其中有一个食谱;该配方可以有多个成分(用外键处理),每个成分可以有一个组件。有几组 table 遵循与此类似的模式,其中有几层
当我添加一个配方时,其中包含一些最终导致相同组件的成分,我收到一条错误消息,指出将配方添加到数据库会导致组件发生主键冲突 table .有没有办法告诉实体,如果一个组件具有相同的主键值,它应该更新而不是插入?我知道您可以使用 context.Recipes.AddOrUpdate(recipe)
在顶层执行此操作,但我如何才能在树结构中的每个子级别实现它?
以下是我已有的实体 classes 的一些总结示例:
public partial class Recipe
{
public int Id { get; set; }
public virtual ICollection<Ingredient> Ingredients { get; set; }
}
public partial class Ingredient
{
public int Id {get;set;}
public int ComponentId { get; set; }
public virtual Component Component { get; set; }
public virtual ICollection<Recipe> Recipes { get; set; }
}
public partial class Component
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
public string Description { get; set; }
public virtual ICollection<Ingredient> Ingredients { get; set; }
}
//在:DbContext class中,有这个:
modelBuilder.Entity<Ingredient>()
.HasMany(e => e.Recipes)
.WithMany(e => e.Ingredients)
.Map(m => m.ToTable("Recipe_Ingredient_Link").MapLeftKey("IngredientId").MapRightKey("RecipeId"));
我收到此错误消息是因为具有相同 Id 的两个组件具有不同的 Ingredients
ICollections 与之关联,导致 Entity 将它们视为不同的对象吗?如果是这样,我该如何解决这个问题?如果不是,是什么问题?
我从现有数据库生成 classes,除了关闭延迟加载外,没有更改它为我创建的代码。
我认为您的问题在于,在从 JSON 到 C# 对象的转换中,您为 JSON 中的每个组件获得了一个单独的对象。这意味着即使两个组件具有相同的 ID,它也是两个不同的对象,就像您也描述的那样。如图所示:
Recipe #1
|
|-- Ingr. #1
| |-- Comp. #1
|
|-- Ingr. #2
| |-- Comp. #2
|
|-- Ingr. #3
|-- Comp. #1 // Same ID as the one for Ingr. 1, but it's a separate C# object
当您尝试添加对象层次结构(通过仅添加 top-level Recipe
)时,Entity Framework 会将每个 C# 对象视为一个单独的实体。因此,即使两个对象共享相同的 ID,也没有逻辑告诉 EF 如何处理它。 IE。如果其他属性(除了 ID)不同,它应该如何表现?
所以我认为您需要做的是确保没有两个对象具有冲突的 ID。您必须遍历对象并确保如果两个组件具有相同的 ID,则需要删除其中一个组件并将 Ingredient
s link 指向同一个 Component
对象,如图所示:
Recipe #1
|
|-- Ingr. #1
| |----------------|
| |
|-- Ingr. #2 |
| |-- Comp. #2 |-- Comp. #1 // Now they point to the same C# object
| |
|-- Ingr. #3 |
|----------------|
我会让你考虑如何编写代码。