前进之路 发表于 2024-11-21 09:05:38

怎样筹划和实现通用唯一 Code 生成方法

在开辟中,尤其是涉及分层结构(如分类、目次、组织等)时,唯一的编码(Code)是一个常见需求。一个好的编码生成器需要确保代码的唯一性、可读性,而且可以或许随着层级的递增动态扩展。本文将探究怎样筹划和实现一个通用的唯一 Code 生成方法。
场景分析


[*] 需求:

[*]第一层的编码规则是 B+两位数字(如 B01)。
[*]第二层是 B+三位数字(如 B01001),第三层以此类推。
[*]编码需唯一,并支持动态生成。
[*]子层级的编码需基于父层级的编码(如 B01 的子级为 B01001)。

[*] 常见的应用场景:

[*]组织架构:如公司 -> 部门 -> 团队。
[*]商品分类:如一级分类 -> 二级分类 -> 三级分类。
[*]文件目次:如文件夹 -> 子文件夹 -> 文件。

筹划要点


[*] 唯一性:

[*]每个编码在其所属层级内必须唯一。
[*]子层级编码必须包含父层级的编码。

[*] 动态扩展性:

[*]层级数不固定,可根据需要自由扩展。

[*] 高效查询:

[*]生成编码时,应只管淘汰对数据库的读写操作,提高性能。

[*] 清晰的规则:

[*]规则简单明白,便于开辟和维护。
[*]不答应有含糊的特殊字符或冗余的空格。

实现思路


[*] 规则定义:

[*]第一层:以 B 开头,后接两位数字(B01)。
[*]第二层:在父级编码底子上追加三位数字(B01001)。
[*]第三层:继续追加三位数字(B01001001)。

[*] 递增逻辑:

[*]查询当前层级的最大编码。
[*]在最大编码的末端递增(如 001 -> 002)。

[*] 默认值生成:

[*]如果层级中无记录,则从 B01 或 001 开始生成。

[*] 数据存储:

[*]数据表需包含以下字段:

[*]Code(编码)
[*]Level(层级)
[*]Pid(父节点 ID,用于关联父层级)
[*]Name(名称,用于展示)


代码实现

以下是利用 C# 的实现示例:
数据库服务层

public async Task<string> GetMaxCodeByLevelAsync(int level, Guid? parentId = null)
{
    if (parentId.HasValue)
    {
      // 查询特定父节点下的最大 Code
      return await _context.SpAdjustmentDicts
            .Where(o => o.Level == level && o.Pid == parentId)
            .OrderByDescending(o => o.Code)
            .Select(o => o.Code)
            .FirstOrDefaultAsync();
    }
    else
    {
      // 查询该层级的最大 Code
      return await _context.SpAdjustmentDicts
            .Where(o => o.Level == level)
            .OrderByDescending(o => o.Code)
            .Select(o => o.Code)
            .FirstOrDefaultAsync();
    }
}
生成编码方法

private async Task<string> GenerateCodeAsync(int level, Guid? parentId = null)
{
    string maxCode = await GetMaxCodeByLevelAsync(level, parentId);

    if (string.IsNullOrEmpty(maxCode))
    {
      if (parentId.HasValue)
      {
            // 子层级的默认起始值
            var parent = await _context.SpAdjustmentDicts.FindAsync(parentId);
            return parent.Code + "001";
      }
      else
      {
            // 第一层默认值
            return "B01";
      }
    }

    // 递增逻辑
    if (parentId.HasValue)
    {
      // 子层级递增
      int subNumber = int.Parse(maxCode.Substring(maxCode.Length - 3)) + 1;
      return maxCode.Substring(0, maxCode.Length - 3) + subNumber.ToString("D3");
    }
    else
    {
      // 第一层递增
      int majorNumber = int.Parse(maxCode.Substring(1)) + 1;
      return "B" + majorNumber.ToString("D2");
    }
}
记录校验与添加

private async Task<SpAdjustmentDict> EnsureRecordExistsAsync(
    string name,
    int level,
    SysUser user,
    Guid? parentId = null)
{
    if (string.IsNullOrEmpty(name)) return null;

    var existingRecord = parentId.HasValue
      ? await _adjustmentDictService.SelectByNameAndLevelAndPid(name, level, parentId.Value)
      : await _adjustmentDictService.SelectByNameAndLevel(name, level);

    if (existingRecord != null) return existingRecord;

    string code = await GenerateCodeAsync(level, parentId);

    var newRecord = new SpAdjustmentDict
    {
      Name = name,
      Code = code,
      Level = level,
      Pid = parentId,
      LogicDelFlg = false,
      InsertBy = user.UserName,
      UpdateBy = user.UserName,
      InsertTime = DateTime.Now,
      UpdateTime = DateTime.Now,
      InsertById = user.Id,
      UpdateById = user.Id
    };

    return await _adjustmentDictService.Add(newRecord);
}
优化与扩展


[*] 并发问题:

[*]为防止并发导致重复编码,可在数据库中为 Code 列添加唯一束缚。
[*]利用事件或锁机制确保线程安全。

[*] 高性能需求:

[*]考虑缓存每个层级的最大编码,淘汰数据库查询频率。

[*] 适配更多规则:

[*]可以通过设置文件或参数传递动态调整编码规则(如修改前缀或位数)。

[*] 日志记录:

[*]在编码生成过程中记录详细日志,便于排查问题。

总结

通过筹划规则清晰、递增逻辑严谨的编码生成方法,可以轻松实现分层结构中的唯一编码需求。这种通用方法适用于多种场景,如组织架构、商品分类等。在实际应用中,根据业务特点调整规则与性能优化策略,可以使编码系统更加高效可靠。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 怎样筹划和实现通用唯一 Code 生成方法