You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# EF Core 实现带ParentId自引用的IssueActivity多明细嵌套保存

实现方案

1. 补充IssueActivityDetail实体的自引用导航属性

你的现有实体只定义了ParentId字段,缺少父子层级的导航属性,需要补充:

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; }
    // 新增自引用导航属性
    public virtual IssueActivitiyDetail? Parent { get; set; }
    public virtual List<IssueActivitiyDetail> Children { get; set; } = new();
}

注:你当前定义的实体名IssueActivitiy存在拼写错误(正确拼写为IssueActivity),建议统一修正避免后续维护问题

2. 修正Fluent API自引用配置

在IssueActivitiyDetail的Configure方法中补充自引用关联配置,注意关闭级联删除避免循环引用异常:

public void Configure(EntityTypeBuilder<IssueActivitiyDetail> modelBuilder)
{
    modelBuilder.ToTable("IssueActivitiyDetail");
    modelBuilder.HasKey(e => e.Id); // 补充遗漏的主键配置
    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.HasOne<IssueActivitiyDetail>(e => e.Parent)
        .WithMany(e => e.Children)
        .HasForeignKey(e => e.ParentId)
        .OnDelete(DeleteBehavior.Restrict); // 禁止级联删除,避免循环引用报错
    modelBuilder.HasOne(d => d.IssueActivity).WithMany(p => p.IssueActivitiyDetails).HasForeignKey(d => d.IssueActivityId).OnDelete(DeleteBehavior.ClientSetNull).HasConstraintName("FK_IssueActivitiy_IssueActivitiyDetail_");
}

3. 修正树形数据转换逻辑

你原来的代码没有递归处理子层级,需要新增递归转换方法,将前端传的树形结构正确映射为EF的实体层级:

// 新增子节点递归转换方法
private IssueActivitiyDetail ConvertDetail(IssueActivitiyDetailInfo input, int roleId)
{
    var detail = new IssueActivitiyDetail
    {
        LineNo = input.LineNo,
        Definition = input.Definition,
        RoleId = roleId,
        Medium = input.Medium,
        Explanation = input.Explanation
    };
    // 递归处理当前节点的所有子节点
    if (input.IssueActivitiyDetailInfos?.Any() == true)
    {
        foreach (var child in input.IssueActivitiyDetailInfos)
        {
            detail.Children.Add(ConvertDetail(child, roleId));
        }
    }
    return detail;
}

// 外层转换逻辑
var vIssueActivities = issueInfo.IssueActivitiyInfos
.Select(a => new IssueActivitiy
{
    Type = a.Type,
    SubActivityNo = a.SubActivityNo,
    SubActivityTitle = a.SubActivityTitle,
    IssueActivitiyDetails = a.IssueActivitiyDetailInfos
        .Select(x => ConvertDetail(x, vUser.RoleId))
        .ToList()
}).ToList();

4. 数据保存

直接将转换后的实体加入DbContext执行保存即可,EF Core会自动处理层级关联的外键填充(包括IssueActivityId和ParentId),不需要手动赋值:

dbContext.IssueActivitiys.AddRange(vIssueActivities);
await dbContext.SaveChangesAsync();

内容的提问来源于stack exchange,提问作者Celal Poyraz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 08:24:12