ASP.NET Core Web API项目多级差异化编号(1、1.a等)实现步骤问询
ASP.NET Core Web API 多级差异化编号实现方案
1. 调整实体模型结构
给检查清单、子检查清单、策略、合规项统一抽象为节点实体(或各实体共享核心字段),新增关键字段以支撑编号生成逻辑:
Id:节点唯一标识ParentId:父节点ID(一级检查清单的ParentId为null)NodeType:枚举类型,区分节点类型(Checklist/SubChecklist/Policy/ComplianceItem)Number:存储生成的差异化编号(如1、1.a、1.1)Name:节点名称(如"安全基线检查清单")
枚举定义示例:
public enum NodeType { Checklist, SubChecklist, Policy, ComplianceItem }
EF Core实体类示例:
public class ChecklistNode { public int Id { get; set; } public int? ParentId { get; set; } public NodeType NodeType { get; set; } public string Number { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; // 导航属性 public ChecklistNode? Parent { get; set; } public ICollection<ChecklistNode> Children { get; set; } = new List<ChecklistNode>(); }
2. 实现编号生成核心逻辑
编写编号生成工具类,根据父节点编号和当前节点类型,生成对应格式的编号:
- 一级检查清单:取数据库中已存在的Checklist数量+1,生成"1"、"2"这类纯数字编号
- 子检查清单:基于父检查清单编号,按字母序列(a、b、c...)拼接,生成"1.a"、"1.b"
- 策略:基于父检查清单编号,按数字序列(1、2、3...)拼接,生成"1.1"、"1.2"
- 合规项:基于父策略编号,按数字序列拼接,生成"1.1.1"、"1.1.2"
工具类代码示例:
public class ChecklistNumberGenerator { private readonly AppDbContext _dbContext; public ChecklistNumberGenerator(AppDbContext dbContext) { _dbContext = dbContext; } public async Task<string> GenerateNumberAsync(int? parentId, NodeType nodeType) { if (parentId == null) { // 生成一级检查清单编号 var count = await _dbContext.ChecklistNodes .Where(n => n.NodeType == NodeType.Checklist) .CountAsync(); return (count + 1).ToString(); } var parentNode = await _dbContext.ChecklistNodes.FindAsync(parentId); if (parentNode == null) throw new ArgumentException("父节点不存在"); switch (nodeType) { case NodeType.SubChecklist: var subCount = await _dbContext.ChecklistNodes .Where(n => n.ParentId == parentId && n.NodeType == NodeType.SubChecklist) .CountAsync(); // 数字转字母:1→a,2→b... char suffix = (char)('a' + subCount); return $"{parentNode.Number}.{suffix}"; case NodeType.Policy: var policyCount = await _dbContext.ChecklistNodes .Where(n => n.ParentId == parentId && n.NodeType == NodeType.Policy) .CountAsync(); return $"{parentNode.Number}.{policyCount + 1}"; case NodeType.ComplianceItem: var complianceCount = await _dbContext.ChecklistNodes .Where(n => n.ParentId == parentId && n.NodeType == NodeType.ComplianceItem) .CountAsync(); return $"{parentNode.Number}.{complianceCount + 1}"; default: throw new ArgumentException("不支持的节点类型"); } } }
3. 在API接口中集成编号生成
在添加节点的API接口中,调用编号生成工具生成编号后,再将节点数据保存到数据库。
API控制器代码示例:
[ApiController] [Route("api/checklist")] public class ChecklistController : ControllerBase { private readonly AppDbContext _dbContext; private readonly ChecklistNumberGenerator _numberGenerator; public ChecklistController(AppDbContext dbContext, ChecklistNumberGenerator numberGenerator) { _dbContext = dbContext; _numberGenerator = numberGenerator; } [HttpPost] public async Task<IActionResult> AddNode([FromBody] AddNodeRequest request) { var nodeNumber = await _numberGenerator.GenerateNumberAsync(request.ParentId, request.NodeType); var newNode = new ChecklistNode { ParentId = request.ParentId, NodeType = request.NodeType, Number = nodeNumber, Name = request.Name }; _dbContext.ChecklistNodes.Add(newNode); await _dbContext.SaveChangesAsync(); return Ok(newNode); } } // 请求DTO public class AddNodeRequest { public int? ParentId { get; set; } public NodeType NodeType { get; set; } public string Name { get; set; } = string.Empty; }
4. 查询与排序优化
查询节点时直接按Number字段排序,编号格式自带层级逻辑,可保证展示顺序符合预期(如"1" < "1.a" < "1.1" < "1.1.1" < "2")。
查询接口示例:
[HttpGet] public async Task<IActionResult> GetAllNodes() { var nodes = await _dbContext.ChecklistNodes .OrderBy(n => n.Number) .ToListAsync(); return Ok(nodes); }
5. 边界场景处理
- 父节点不存在:在编号生成方法中检测并抛出明确异常
- 子检查清单数量超26个:扩展字母序列为"aa"、"ab"格式,修改字母转换逻辑
- 节点类型不匹配:在接口中增加校验,禁止给SubChecklist添加Policy子节点等非法操作
内容的提问来源于stack exchange,提问作者332-08 Pranav Bodakhe
相关产品推荐
相关产品推荐

