【问题标题】:Inserting / saving entity with nested children entities with Entity Framework使用实体框架插入/保存具有嵌套子实体的实体
【发布时间】:2020-11-28 09:10:08
【问题描述】:

以下是课程:

public class Parent 
{
     public int Id { get; set; }
     public string Name { get; set; }
     public IEnumerable<Child> Childs { get; set; }
     public IEnumerable<ParentLog> Logs { get; set; }
}

public class ParentLog 
{
     public int Id { get; set; }
     public DateTime On { get; set; }
     public string Note { get; set; }
     public int ParentId { get; set; }
     public string Name { get; set; }
}

public class Child 
{
     public int Id { get; set; }
     public string Name { get; set; }
     public int ParentId { get; set; }
     public IEnumerable<ChildLog> Logs { get; set; }
}

public class ChildLog 
{
     public int Id { get; set; }
     public DateTime On { get; set; }
     public string Note { get; set; }
     public int ChildId { get; set; }
     public string Name { get; set; }
     public int ParentId { get; set; }
}

DbContext:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
     modelBuilder.Entity<Parent>().HasMany(a => a.Childs);
     modelBuilder.Entity<Parent>().HasMany(a => a.Logs);
     modelBuilder.Entity<Child>().HasMany(a => a.Logs);
}

这个想法是当父母和孩子被保存时,父母和孩子的日志条目也被保存。这行得通。

保存代码:

DateTime now = DateTime.Now;
foreach (var a in parents)
{
     a.Logs = new List<ParentLog>();
     a.Logs.Add(new ParentLog
     {
          On = now,
          Note = "Created",
          Name = a.Name
     });

     foreach(var b in a.Childs)
     {
         b.Logs = new List<ChildLog>();
         b.Logs.Add(new ChildLog
         {
              On = now,
              Note = "Created",
              Name = b.Name,
              ParentId = b.ParentId //not needed with the Accepted Answer.
          });
     }
}

int recordsAffected = new ParentRepository().SaveParents(parents);
public int SaveParents(List<Parent> items)
{
     foreach(var item in items)
     {
          _db.Parents.Add(item);
     }

     return _db.SaveChanges();
}

我遇到的问题是ChildLog.ParentId。它没有预期值的值,我想是来自Child.ParentId

我的问题,如何解决?

【问题讨论】:

  • 由于ChildLog 与实体Parent 没有任何直接关系,只需从Child 实体保存更改日志...您必须将Child.ParentId 属性值传递给@987654332 @属性。
  • Luis,我也试过了,为 ChildLog.ParentId 保存的值仍然是 0 ,而对于 ChildLog.ChildId,它是实际的 Child.Id。
  • 您没有显示您遇到问题的保存代码。
  • Gert Arnold,我刚刚添加了保存代码。
  • 没有显示最重要的部分:所有这些对象都是新的吗?我猜他们是,所以ParentId 根本还没有它的生成值。您只能在保存后分配它们。

标签: c# entity-framework


【解决方案1】:

向 Child 模型添加导航属性 ChildLog >Child。

然后您就可以通过 Child 访问 ParentId。

进一步阅读 - https://docs.microsoft.com/en-us/ef/ef6/fundamentals/relationships

【讨论】:

    【解决方案2】:

    事实证明 EF 可以在一个 SaveChanges() 中处理它。不过,我需要明确定义关系。

    以下是已更新的类:

    public class Child 
    {
         public int Id { get; set; }
         public string Name { get; set; }
         public int ParentId { get; set; }
         public IEnumerable<ChildLog> Logs { get; set; }
         //Added
         public Parent Parent { get; set; }
    }
    
    public class ChildLog 
    {
         public int Id { get; set; }
         public DateTime On { get; set; }
         public string Note { get; set; }
         public int ChildId { get; set; }
         public string Name { get; set; }
         public int ParentId { get; set; }
         //Added
         public Child Child { get; set; }
    }
    

    这是 DbContext 中更新后的 OnModelCreating 方法:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
         var parent = modelBuilder.Entity<Parent>();
         parent.HasKey(a => a.Id);
         parent.Property(a => a.ParentId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
         parent.HasMany(a => a.Logs); //ParentLog
    
         var child = modelBuilder.Entity<Child>();
         child.HasKey(a => new { a.Id, a.ParentId });
         child.Property(a => a.ChildId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
         child.HasRequired(a => a.Parent).WithMany(a => a.Childs).HasForeignKey(a => a.ParentId);
    
         var childLog = modelBuilder.Entity<ChildLog>();
         childLog.HasKey(a => new { a.Id, a.ChildId, a.ParentId });
         childLog.Property(a => a.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
         childLog.HasRequired(a => a.Child).WithMany(a => a.Logs).HasForeignKey(a => new { a.ChildId, a.ParentId });
    }
    

    这对我有帮助 -> How to fix: The number of properties in the Dependent and Principal Roles in a relationship constraint must be identical?

    这件小而重要的事情真是麻烦。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多