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

news2024/11/24 15:40:13

在开发中,尤其是涉及分层结构(如分类、目录、组织等)时,唯一的编码(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.coloradmin.cn/o/2246738.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

KubeSphere 最佳实战:K8s 构建高可用、高性能 Redis 集群实战指南

首发&#xff1a;运维有术。 本指南将逐步引导您完成以下关键任务&#xff1a; 安装 Redis&#xff1a;使用 StatefulSet 部署 Redis。自动或手动配置 Redis 集群&#xff1a;使用命令行工具初始化 Redis 集群。Redis 性能测试&#xff1a;使用 Redis 自带的 Benchmark 工具进…

apr共享内存

下载&#xff1a; Download - The Apache Portable Runtime Project 编译&#xff1a; 使用cmake-gui生成库&#xff1a; apr-1.lib aprapp-1.lib libapr-1.lib libaprapp-1.lib libapr-1.dll 在Developer PowerShell for VS 2019中&#xff1a; 执行nmake -f Makefile.win来…

Javaweb前端HTML css 整体布局

最后一个是线条颜色 盒子&#xff0c;整体还是300&#xff0c;400

5.STM32之通信接口《精讲》之USART通信---实验串口接收程序

根据上节&#xff0c;我们一已经完成了串口发送程序的代码&#xff0c;并且深入的解析探索了串口的原理&#xff0c;接下来&#xff0c;Whappy小编将带领大家进入串口接收程序的探索与实验&#xff0c;并将结合上一节串口发送一起来完成串口的发送和接收实验。 上来两张图 上图…

借助算力云跑模型

算力平台&#xff1a;FunHPC | 算力简单易用 AI乐趣丛生 该文章只讲述了最基本的使用步骤&#xff08;因为我也不熟练&#xff09;。 【注】&#xff1a;进入平台&#xff0c;注册登录账号后&#xff0c;才能租用。学生认证&#xff0b;实名认证会有免费的算力资源&#xff0…

SpringMVC 执行流程详解

目录 前言1. SpringMVC 的核心组件概述1.1 DispatcherServlet1.2 HandlerMapping1.3 HandlerAdapter1.4 拦截器&#xff08;HandlerInterceptor&#xff09;1.5 ViewResolver 2. SpringMVC 的执行流程详解2.1 接收请求并分发2.2 获取 HandlerExecutionChain2.3 获取 HandlerAda…

安卓应用安装过程学习

声明&#xff1a;此文章来自http://shuwoom.com/?p60的学习记录 启动式安装 public static final IPackageManager main(Context context, Installer installer,boolean factoryTest, boolean onlyCore) {PackageManagerService m new PackageManagerService(context, inst…

如何通过OpenSSL来创建自签名的CA证书?

通过创建自签名CA证书可以让我们在没有商业支持的情况下学习与研究PKI&#xff08;公钥基础设施&#xff09;和SSL/TLS技术&#xff0c;本文将详细介绍如何通过OpenSSL来创建自签名的CA证书。 1. 初衷&#xff1a;为什么需要创建自签名CA证书&#xff1f; 除了开篇引言中提到的…

mac安装Pytest、Allure、brew

安装环境 安装pytest 命令 pip3 install pytest 安装allure 命令&#xff1a;brew install allure 好吧 那我们在安装allure之前 我们先安装brew 安装brew 去了官网复制了命令 还是无法下载 如果你们也和我一样可以用这个方法哦 使用国内的代码仓库来执行brew的安装脚本…

Python中“暂停”(time.sleep?input?)

input函数最是经典&#xff0c;在多种实现中简单粗暴单纯而经济。 (笔记模板由python脚本于2024年11月22日 10:58:38创建&#xff0c;本篇笔记适合比较熟悉python的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大…

刷题——【模板】二维前缀和

前缀和 题目题目链接题解方法一方法二 题目 描述 给你一个 n 行 m 列的矩阵 A &#xff0c;下标从1开始。 接下来有 q 次查询&#xff0c;每次查询输入 4 个参数 x1 , y1 , x2 , y2 请输出以 (x1, y1) 为左上角 , (x2,y2) 为右下角的子矩阵的和&#xff0c; 输入描述&#x…

10 - Clickhouse集群部署以及副本和分片

目 一、副本 1、简介 2、副本写入流程 3、副本配置步骤 3.1、启动zookeeper集群 3.2、在 hallo100 的/etc/clickhouse-server/config.d 目录下创建一个名为metrika.xml 的配置文件,内容如下&#xff1a; 3.3、在 hallo100 的/etc/clickhouse-server/config.xml 中增加如…

Ubuntu24.04LTS设置root用户可远程登录

Ubuntu24.04LTS设置root用户可远程登录 文章目录 Ubuntu24.04LTS设置root用户可远程登录1. 设置root密码2. 设置root用户可远程登录1. 查看ssh服务是否安装2. 安装ssh服务3. 再次查看ssh服务是否安装4. 配置ssh文件5. 重启ssh服务6. root远程登录 1. 设置root密码 Ubuntu安装后…

DMA理论篇

DMA理论篇 简介 传统的数据传输都是需要CPU来实现&#xff0c;从一个地方拷贝到另一个地方&#xff1b;而DMA(Direct Memory Access)则不完全依赖CPU&#xff0c;DMA更新芯片SOC的一个控制器&#xff0c;他可以控制数据从内存中传输到另一个地方(外设、soc其它模块)&#xff…

理解原子变量之三:原子性与memory_order_relaxed

目录 CPU与内存的关系 原子性 典型使用场景 在本系列的第一篇文章理解原子变量之一&#xff1a;从互斥锁到原子变量&#xff0c;最粗浅的认识_原子互斥-CSDN博客&#xff0c;我通过几个实例从感性认识的角度介绍了原子性。本文在第一篇文章的基础上&#xff0c;从理性认识的…

医院信息化与智能化系统(22)

医院信息化与智能化系统(22) 这里只描述对应过程&#xff0c;和可能遇到的问题及解决办法以及对应的参考链接&#xff0c;并不会直接每一步详细配置 如果你想通过文字描述或代码画流程图&#xff0c;可以试试PlantUML&#xff0c;告诉GPT你的文件结构&#xff0c;让他给你对应…

青少年编程等级考试C++一级,硬币反转问题

代码 #include<iostream>using namespace std;bool a[300];int main(){ int n,m; cin >> n >> m; for(int i 1;i < m;i) { for (int j 1;j < n;j) { if( j % i 0) { a[j] !a[j];…

数字化工厂 MES试点方案全解析(二)

生产过程监控与数据采集 在生产线上部署各类传感器、数据采集终端等设备&#xff0c;与 MES 系统相连&#xff0c;实时采集生产数据&#xff0c;如设备运行参数&#xff08;温度、压力、转速等&#xff09;、产品加工数据&#xff08;尺寸、重量、加工时间等&#xff09;、物料…

动态规划子数组系列一>最长湍流子数组

1.题目&#xff1a; 解析&#xff1a; 代码&#xff1a; public int maxTurbulenceSize(int[] arr) {int n arr.length;int[] f new int[n];int[] g new int[n];for(int i 0; i < n; i)f[i] g[i] 1;int ret 1;for(int i 1; i < n-1; i,m. l.kmddsfsdafsd){int…

(十一)Python字符串常用操作

一、访问字符串值 Python访问子字符串变量&#xff0c;可以使用方括号来截取字符串。与列表的索引一样&#xff0c;字符串索引从0开始。 hh"LaoTie 666" hh[2] mm"床前明月光" mm[3] 字符串的索引值可以为负值。若索引值为负数&#xff0c;则表示由字符…