asp.net自定义表主键解决方案(附代码Demo实战)
概述
一般情况下我们在设计表时主键都是自增长的,我们都是采用数据库本身提供的主键自增机制,Sqlserver一般是用IDENTITY(1,1)这个来标识,Oracle一般是用触发器,在大多数应用场景下这些机制基本上是够用的,但是在某些场景下如果需要自定义主键生成机制,例如生成L0000001、010001、000001等这些主键,利用关系数据库本身的机制就满足不了了。
这里介绍一种能够灵活定制主键的方式,它主要通过一定的生成机制来生成符合要求的主键,这里拿一个主键值初始化值来介绍:
主键初始化值 |
前缀 |
长度 |
备注 |
L0000001 |
L |
7 |
|
010001 |
01 |
4 |
|
000001 |
|
6 |
|
需求分析及设计
|
功能 |
质量 |
约束 |
组织、用户、开发 |
1、 主键灵活定制; 2、 主键生成表数据结构设计; 3、 主键生成调用接口API封装;
|
1、 安全性; 2、 通用性; 3、 性能; 4、 灵活性; |
1、 读写线程问题; 2、 无需额外配置,自动记录主键最大值; |
数据结构设计
名称 |
代码 |
注释 |
数据类型 |
长度 |
是否主键 |
表名称 |
GC017_Table_Name |
|
varchar(100) |
100 |
TRUE |
前缀编码 |
GC017_Parent_Code |
|
varchar(20) |
20 |
TRUE |
编码级别 |
GC017_Code_Level |
|
varchar(20) |
20 |
TRUE |
最大编码 |
GC017_Max_Code |
|
varchar(20) |
20 |
FALSE |
列名称 |
GC017_Column_Name |
|
varchar(20) |
20 |
TRUE |
列类型 |
GC017_Column_Type |
|
varchar(10) |
10 |
FALSE |
代码赏析
1、核心代码主要有两个:ITableCode接口和它的实现类TableCode,调用方式如下:
ITableCode tablecode = new TableCode();
// 模式1:生成主键id,参数依次为表名称、主键、主键生成长度,传入6表示000001
string id = tablecode.NewCode("tableName", "column", "6");
// 模式2:生成主键id,表示0010001
id = tablecode.NewCode("tableName", "column","2","001","4");
2、TableCode中的生成编码的核心方法:

private static readonly ReaderWriterLock l = new ReaderWriterLock();
private static readonly string prefix = string.Empty;
/// <summary>
/// 根据规则生成主键Tablecode
/// </summary>
/// <param name="pTblName">表名称</param>
/// <param name="pColumn">列名称</param>
/// <param name="pLevel">级别默认为空</param>
/// <param name="pParentCode">前缀</param>
/// <param name="pLength">长度</param>
/// <returns></returns>
public string NewCode(string pTblName, string pColumn, string pLevel, string pParentCode, string pLength)
{
try
{
l.AcquireWriterLock(Timeout.Infinite);
if (pParentCode.Equals(string.Empty))
pParentCode = "0";
if (pLevel.Equals(string.Empty))
pLevel = "1";
ArrayList objList;
objList = GetData(pTblName, pColumn, pLevel, pParentCode);
if (!pLevel.Equals("1"))
{
if (!pParentCode.Equals("0"))
{
if (objList.Equals(null))
{
string newcode = pParentCode + IncCode(string.Empty, pLength);
InsertData(pTblName, pColumn, pLevel, pParentCode, newcode);
return newcode;
}
if (objList.Count == 0)
{
string newcode = pParentCode + IncCode(string.Empty, pLength);
InsertData(pTblName, pColumn, pLevel, pParentCode, newcode);
return newcode;
}
if (objList.Count == 1)
{
string newcode = IncCode(((TableCodeInfo)objList[0]).MaxCode, pLength);
SetData(pTblName, pColumn, pLevel, pParentCode, newcode);
return newcode;
}
}
}
if (objList.Equals(null))
{
string newcode = IncCode(string.Empty, pLength);
InsertData(pTblName, pColumn, pLevel, pParentCode, newcode);
return newcode;
}
if (objList.Count == 0)
{
string newcode = IncCode(string.Empty, pLength);
InsertData(pTblName, pColumn, pLevel, pParentCode, newcode);
return newcode;
}
if (objList.Count == 1)
{
string newcode = IncCode(((TableCodeInfo)objList[0]).MaxCode, pLength);
SetData(pTblName, pColumn, pLevel, pParentCode, newcode);
return newcode;
}
}
finally
{
l.ReleaseWriterLock();
}
return string.Empty;
}
这里用到了多线程的ReaderWriterLock,方法中调用l.AcquireWriterLock(Timeout.Infinite);这样就可以保证读的时候是多线程,写的时候是单线程,避免了主键错乱的问题;
代码完整Demo下载:SystableCode.rar
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构