当前位置: 首页 > article >正文

如何设计和实现通用唯一 Code 生成方法

在开发中,尤其是涉及分层结构(如分类、目录、组织等)时,唯一的编码(Code)是一个常见需求。一个好的编码生成器需要确保代码的唯一性、可读性,并且能够随着层级的递增动态扩展。本文将探讨如何设计和实现一个通用的唯一 Code 生成方法。


场景分析
  1. 需求

    • 第一层的编码规则是 B+两位数字(如 B01)。
    • 第二层是 B+三位数字(如 B01001),第三层以此类推。
    • 编码需唯一,并支持动态生成。
    • 子层级的编码需基于父层级的编码(如 B01 的子级为 B01001)。
  2. 常见的应用场景

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

设计要点
  1. 唯一性

    • 每个编码在其所属层级内必须唯一。
    • 子层级编码必须包含父层级的编码。
  2. 动态扩展性

    • 层级数不固定,可根据需要自由扩展。
  3. 高效查询

    • 生成编码时,应尽量减少对数据库的读写操作,提高性能。
  4. 清晰的规则

    • 规则简单明了,便于开发和维护。
    • 不允许有模糊的特殊字符或冗余的空格。

实现思路
  1. 规则定义

    • 第一层:以 B 开头,后接两位数字(B01)。
    • 第二层:在父级编码基础上追加三位数字(B01001)。
    • 第三层:继续追加三位数字(B01001001)。
  2. 递增逻辑

    • 查询当前层级的最大编码。
    • 在最大编码的末尾递增(如 001 -> 002)。
  3. 默认值生成

    • 如果层级中无记录,则从 B01001 开始生成。
  4. 数据存储

    • 数据表需包含以下字段:
      • 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);
}

优化与扩展
  1. 并发问题

    • 为防止并发导致重复编码,可在数据库中为 Code 列添加唯一约束。
    • 使用事务或锁机制确保线程安全。
  2. 高性能需求

    • 考虑缓存每个层级的最大编码,减少数据库查询频率。
  3. 适配更多规则

    • 可以通过配置文件或参数传递动态调整编码规则(如修改前缀或位数)。
  4. 日志记录

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

总结

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


http://www.kler.cn/a/407888.html

相关文章:

  • mayo介绍和QTqmake编译基于Opencascade开发的mayo工程-小白配置
  • STL——string类常用接口说明
  • 双因子认证:统一运维平台安全管理策略
  • 瑞佑液晶控制芯片RA6807系列介绍 (三)软件代码详解 Part.10(让PNG图片动起来)完结篇
  • 计算机网络:运输层 —— TCP 的超时重传机制
  • Lua 实现继承的一种方式
  • 从数据提取到管理:TextIn平台的全面解析与产品体验
  • Elasticsearch客户端在和集群连接时,如何选择特定的节点执行请求的?
  • 网络安全 - DOS
  • 解决k8s拉取私有镜像401 Unauthorized 问题
  • 二分排序
  • vue基于高德地图实现城市管网压力点、管线、测距、测面积、绘制多边形、绘制圆代码
  • React 组件生命周期
  • uniapp调整webview的大小与位置,解决遮挡问题
  • ElementUI之el-date-picker禁选配置
  • ESP8266 AP模式TCP服务器 电脑手机网络调试助手
  • 设计模式-创建型-原型模式
  • aws 小白入门,VPC 子网、路由表、互联网网关
  • 链表算法速成计划
  • 探索C++中的map和set容器
  • 【jvm】从字节码角度看待对象创建流程
  • Claude Opus MetaPrompt 系统详解
  • 论文阅读 SimpleNet: A Simple Network for Image Anomaly Detection and Localization
  • 【C++】踏上C++学习之旅(十):深入“类和对象“世界,掌握编程黄金法则(五)(最终篇,内含初始化列表、静态成员、友元以及内部类等等)
  • Spring 中的 ProxyFactory 创建代理对象
  • i春秋-123(文件上传绕过,双写绕过)