插入新实体而不创建子实体(如果存在)

Posted

技术标签:

【中文标题】插入新实体而不创建子实体(如果存在)【英文标题】:Insert a new entity without creating child entities if they exist 【发布时间】:2015-03-02 11:46:44 【问题描述】:

我使用的是代码优先的 EF,我有这样的模型:

public class Product

    [Key]
    public int Id  get; set; 

    [Required]
    public string Name  get; set; 

    public Customer Customer  get; set; 


public class Customer 

    public Customer ()
    
        Products = new List<Product>();
    

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int Id  get; set; 

    // more stuff snipped...

    public ICollection<Product> Products get; set; 

我收到了客户 ID 以及产品 ID 列表。当数据库中不存在产品时,我想添加它:

    var newProduct = new Product Id = id, Name = "<no name yet>", Customer = customer ;
    InsertProduct(newProduct);

问题在于 EF 尝试级联更改并尝试插入一个新的 Customer 对象,其 ID 与现有对象相同,因此它失败了。我该如何解决?

这是插入方法:

    public void InsertProduct(Product item)
    
        CustomerContext.Entry(item).State = EntityState.Added;
        CustomerContext.Set<Product>().Add(item);
    

【问题讨论】:

【参考方案1】:

取自here.

添加具有现有子对象(数据库中存在的对象)的新实体时,如果 EF 未跟踪子对象,则将重新插入子对象。除非您先手动附加子对象。

尝试如下设置子对象状态:

public void InsertProduct(Product item)

    // Calling this code before the context is aware of the Child
    // objects will cause the context to attach the Child objects to the     
    // context and then set the state.
    // CustomerContext.Entry(childitem).State = EntityState.Unchanged
    CustomerContext.Entry(item.ChildObject).State = EntityState.Modified;

    CustomerContext.Entry(item).State = EntityState.Added;
    CustomerContext.Set<Product>().Add(item);

【讨论】:

【参考方案2】:

如果给父类添加外键会更容易:

public class Product

    ....

    public int CustomerId  get; set; 

    public Customer Customer  get; set; 

然后当你要插入的时候,设置外键而不是导航属性:

    var newProduct = new Product
        
          Id = id, 
          Name = "<no name yet>", 
          CustomerId = customer.Id 
       ;
   InsertProduct(newProduct);

参考资料:

Why does Entity Framework Reinsert Existing Objects into My Database?

Making Do with Absent Foreign Keys

【讨论】:

以上是关于插入新实体而不创建子实体(如果存在)的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQl 正确锁定新实体的创建

Coredata关系实体创建

EF6 vs Entity Framework Core:插入实体而不将主键(身份)重置为零

如果存在则更新行否则使用实体框架插入逻辑[关闭]

使用 web api 发布/创建子实体对象时如何设置父实体 ID

bash shell和进程