使用 EF 核心将多个关系数据添加到 SQL Server

Posted

技术标签:

【中文标题】使用 EF 核心将多个关系数据添加到 SQL Server【英文标题】:Add multiple relational data into SQL server using EF core 【发布时间】:2021-12-03 07:54:43 【问题描述】:

我正在尝试使用 EF core 5 将多个关系数据插入 SQL Server DB。 我想插入多个父母和多个孩子。父母和孩子是一对多的关系。我正在尝试使用 context.AddRang(lstparents) 它仅为一个父母插入子实体数据,而其他父母则没有条目。你能帮我解决这个问题吗?

我的模特

    Public class Parent
    
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
      Public int64 Id get; set;// this is identity column
    
      Public string Name  get; set;
    
      Public List<Child> child  get; set;
    

    Public class Child
    
       [Key]
       [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
       Public int64 id  get; set; // identity column
       Public string ChildName  get; set;
    
       Public int64 ParentId  get; set;
    
       [Foreign key("ParentId")]
       Public Parent parent  get; set;
    


// Here is insertion logic

Public void main(string[] args)


List<Child> lstChild = new List<Child> () 
                       
                        new Child ChildName= "Child1Name", 
                        new Child ChildName= "Child2Name", 
                        new Child ChildName= "Child3Name" 
                      ; 
List<Parent> lstparents = new List<Parent>()
                        
                        new Parent Name = "xyz", Child= lstChild , 
                        new Parent Name = "xyz1", Child= lstChild 
                       ;
Context.AddRangeAsync(lstparents); 
Context.SaveChangesAsync();



我也尝试了以下选项,但遇到了另一个问题。

选项 1:

Public void main(string[] args)
    
    
    List<Child> lstChild = new List<Child> () 
                           
                            new Child ChildName= "Child1Name", 
                            new Child ChildName= "Child2Name", 
                            new Child ChildName= "Child3Name" 
                          ; 
    List<Parent> lstparents = new List<Parent>()
                            
                            new Parent Name = "xyz", Child= lstChild , 
                            new Parent Name = "xyz1", Child= lstChild 
                           ;
    foreach(var item in lstparents)
    
        Context.Add(item); 
        foreach(var child in lstChild)
        
            Context.Add(child); 
         
     
     Context.SaveChangesAsync();   
    

选项2: 在下面的代码行中,我收到一个错误 “当 IDENTITY_INSERT 设置为 OFF 时,无法为表中的标识列插入显式值”

Public void main(string[] args)

    List<Child> lstChild = new List<Child> () 
                           
                            new Child ChildName= "Child1Name", 
                            new Child ChildName= "Child2Name", 
                            new Child ChildName= "Child3Name" 
                          ; 
    List<Parent> lstparents = new List<Parent>()
                            
                            new Parent Name = "xyz", Child= lstChild , 
                            new Parent Name = "xyz1", Child= lstChild 
                           ;
    foreach(var item in lstparents)
    
        Context.Entry(item).State=EntityState.Added; 
        foreach(var child in lstChild)
        
            Context.Entry(child).State=EntityState.Added; 
         
     
     Context.SaveChangesAsync();   
    

【问题讨论】:

【参考方案1】:

由于您有一对多的关系(一个父母可以有多个孩子),您不能将一个孩子集添加到多个父母。如果需要,需要配置多对多关系。因此,如果您想添加 2 个父母,则必须创建 2 个孩子列表,而不是一个

List<Child> childList1 = new List<Child> () 
                       
                        new Child ChildName= "Child1Name", 
                        new Child ChildName= "Child2Name", 
                        new Child ChildName= "Child3Name" 
                      ; 
List<Child> childList2 = new List<Child> () 
                       
                        new Child ChildName= "Child4Name", 
                        new Child ChildName= "Child5Name", 
                        new Child ChildName= "Child6Name" 
                      ; 
List<Parent> lstparents = new List<Parent>()
                        
                        new Parent Name = "parent1", Child= childList1 , 
                        new Parent Name = "parent2", Child= childList2  
                       ;

由于你的 main 不是异步的,你只能使用同步操作

Context.AddRange(lstparents); 
Context.SaveChanges();

恕我直言,让 ParentId 可以为空可能是个好主意

 public long? ParentId  get; set;

如果您需要添加多对多,则需要添加 ParentChild 表。

如果你使用net5+,ef core可以为你添加,你只需要改变navigaion属性

 Public class Parent
    
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
      public long Id get; set;// this is identity column
    
      public string Name  get; set;
    
      public virtual ICollection<Child> Childs  get; set;
    

    Public class Child
    
       [Key]
       [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
       public long Id  get; set; // identity column
       public string ChildName  get; set;
          
       public virtual ICollecton<Parent> Parents  get; set;
    

【讨论】:

正如你所说的,我需要一个父母和多个孩子。就我而言,我想将具有不同主键的相同子级添加到不同的父级。我的子列表将是相同的,但在插入数据库时​​,每个父级都有不同的主键。我们可以在 EF Core 中做到这一点吗? @user1776386 我更新了我的答案。在此之后,您将不得不再次干净迁移到 Db。 @user1776386 "我想将 same 具有 different 主键的子级添加到不同的父级" 他们是 不 如果 PK(实体身份)不同,则相同。具有相同的名称和其他属性不会使它们相同。使用 分离 对象和列表,如答案开头的 Serge 所示。

以上是关于使用 EF 核心将多个关系数据添加到 SQL Server的主要内容,如果未能解决你的问题,请参考以下文章

将一个对象插入多个关系 - IOS核心数据

EF Core 过滤掉多对多关系中的重复实体

EF 核心。两个实体(表)之间的多个一对一或零关系

为一个对象快速保存多个核心数据关系

如何仅将具有不同属性的对象添加到核心数据到多关系 NSSet

为啥实体框架核心加载实体的关系而不添加包含