简体   繁体   English

实体框架核心嵌套 object 与自身 parentId

[英]entity framework core nested object with self parentId

I have a treetable structure and this data comes to me from the frontend.我有一个树表结构,这些数据来自前端。 In this treetable structure, there is IssueActivity and IssueActivityDetail for details of this issue.在这个树形表结构中,有 IssueActivity 和 IssueActivityDetail 来了解这个问题的细节。 Now my question is, more than one IssueActivityDetail field can be added to this IssueActivity field.现在我的问题是,这个 IssueActivity 字段可以添加多个 IssueActivityDetail 字段。 How can I do this on the c# ef core side?如何在 c# ef 核心端执行此操作? I tried to do it with the logic of ParentId.我试图用 ParentId 的逻辑来做。 My Entity structures are as follows.我的实体结构如下。 I did not add the parentId in FluenApi because I did not fully understand it.我没有在 FluenApi 中添加 parentId,因为我没有完全理解它。

My IssueActivity table.我的问题活动表。


public partial class IssueActivitiy
{
public int Id { get; set; }
public int IssueId { get; set; }
public byte Type { get; set; }
public short SubActivityNo { get; set; }
public string SubActivityTitle { get; set; }
public virtual Issue Issue { get; set; }
public virtual List<IssueActivitiyDetail> IssueActivitiyDetails { get; set; }
}

My IssueActivityDetail table.我的 IssueActivityDetail 表。


public partial class IssueActivitiyDetail
{
public int Id { get; set; }
public int IssueActivityId { get; set; }
public short LineNo { get; set; }
public string Definition { get; set; }
public byte RoleId { get; set; }
public byte Medium { get; set; }
public string Explanation { get; set; }
public int? ParentId { get; set; }
public virtual IssueActivitiy IssueActivity { get; set; }
}

FluentApi Configuration. FluentApi 配置。


public void Configure(EntityTypeBuilder<IssueActivitiy> modelBuilder)
{
modelBuilder.ToTable("IssueActivitiy");
modelBuilder.HasKey(a => a.Id);
modelBuilder.Property(e => e.SubActivityNo).HasComment("Sıra No");
modelBuilder.Property(e => e.SubActivityTitle).HasMaxLength(256).IsUnicode(false);
modelBuilder.Property(e => e.Type).HasDefaultValueSql("((1))").HasComment("1) Temel Aktivite\r\n2) Alternatif Aktivite\r\n3) İşlem İptal Aktivite");
modelBuilder.HasOne(d => d.Issue).WithMany(p => p.IssueActivitiys).HasForeignKey(d => d.IssueId).OnDelete(DeleteBehavior.ClientSetNull).HasConstraintName("FK_Issue_IssueActivitiy_Id");
}
public void Configure(EntityTypeBuilder<IssueActivitiyDetail> modelBuilder)
{
modelBuilder.ToTable("IssueActivitiyDetail");
modelBuilder.Property(e => e.Definition).IsRequired().HasMaxLength(2048).IsUnicode(false).HasComment("Açıklama");
modelBuilder.Property(e => e.Explanation).HasMaxLength(2048).IsUnicode(false).HasComment("Açıklama");
modelBuilder.Property(e => e.IssueActivityId).HasComment("Konu Id");
modelBuilder.Property(e => e.LineNo).HasComment("Sıra No");
modelBuilder.Property(e => e.Medium).HasComment("Ortam (Excel, Mail vb.)");
modelBuilder.Property(e => e.RoleId).HasComment("Rol");
modelBuilder.Property(e => e.ParentId);
modelBuilder.HasOne(d => d.IssueActivity).WithMany(p => p.IssueActivitiyDetails).HasForeignKey(d => d.IssueActivityId).OnDelete(DeleteBehavior.ClientSetNull).HasConstraintName("FK_IssueActivitiy_IssueActivitiyDetail_");
}

Web Api is also the place where I try to receive and process the data, but I played a lot and couldn't do it correctly. Web Api也是我尝试接收和处理数据的地方,但是玩了很多,都做不好。

var vIssueActivity = issueInfo.IssueActivitiyInfos
.Select(a => new IssueActivitiy
{
Type = a.Type,
SubActivityNo = a.SubActivityNo,
SubActivityTitle = a.SubActivityTitle,
IssueActivitiyDetails = a.IssueActivitiyDetailInfos
.Select(x => new IssueActivitiyDetail
{
 
LineNo = x.LineNo,
Definition = x.Definition,
RoleId = vUser.RoleId,
Medium = x.Medium,
Explanation = x.Explanation,
IssueActivityDetail = new List<IssueActivitiyDetail> { }
}).ToList()
});

You don't need to keep ParentId property in IssueActivityDetail .您不需要在IssueActivityDetail中保留ParentId属性。

public partial class IssueActivitiy
{
    ...
    public virtual List<IssueActivitiyDetail> IssueActivitiyDetails { get; set; }
}
public partial class IssueActivitiyDetail
{
    ...
    public virtual IssueActivitiy IssueActivity { get; set; }
}

Your configuration looks not wrong.你的配置看起来没有错。

Maybe you can use Include when getting the entity from db context.从数据库上下文中获取实体时,也许您可以使用Include

var issueActivity = context.IssueActivities.Include(x => x.IssueActivityDetails).FirstOrDefault();

You can accomplish this by retrieving all the entries from the database.您可以通过从数据库中检索所有条目来完成此操作。 Then select the Root node and then let EF Core mapping do the rest.然后 select 根节点,然后让 EF Core 映射做 rest。

public class TreeNode 
{
    public bool IsRoot { get; set; }
    public int? ParentNodeId {get; set;}
    public virtual List<TreeNode> ChildNodes {get; set;}
}

public class TreeNodeRepository 
{

  public async Task<TreeNode> GetTreeStructure()
  {
      var allNodes = await _context.TreeNodes.ToListAsync();

      return allNodes.FirstOrDefault(t => t.IsRoot);
  }

}

You could argue that ParentId == null would also imply that it's a parent node.您可能会争辩说ParentId == null也暗示它是一个父节点。 this just makes the example given more tuitive imo.这只是使给出的示例更加直观。

You should consider performance, how many nodes will become an issue, is it exposed through a web-api and would iterating over the nodes be more efficient.您应该考虑性能,有多少节点将成为一个问题,它是否通过 web-api 公开并且迭代节点会更有效。 So you wouldn't have to load the entire Tree into memory each time but let clients handle that instead.因此,您不必每次都将整个 Tree 加载到 memory 中,而是让客户端来处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM