博客
关于我
C# 生成编号(防并发)
阅读量:409 次
发布时间:2019-03-06

本文共 5055 字,大约阅读时间需要 16 分钟。

今天抽了点时间,写了一个通用的生成编号的程序!

我的生成规则为年月日+两位编号,即:yyyyMMdd+两位编号,譬如:2018101001 / 2018101002 / 2018101003

首先,一个项目中有很多表需要生成编号,譬如:产品编号,评估编号,学生学号等

下面看看我的思路,如下:

首先创建一张表,如下:

create table CM_CodeNo(Id int identity(1,1) primary key not null,CodeCate varchar(50) not null unique,--现场考察 非设计类履约评估等VersionNum TimeStamp not null,CodeYear int,CodeMonth int,CodeDay int,CodeValue varchar(20),CodeCount int,AddTime datetime default(getdate()),)
View Code

简单解读下这张表的构造:

CodeCate:编号分类,譬如:产品编号、评估编号等

VersionNum:乐观锁版本号,用于处理并发,有兴趣的可参考鄙人的博客:https://www.cnblogs.com/chenwolong/p/BF.html#4094056

CodeYear:年

CodeMonth:月

CodeDay:日

CodeCount:代表今天生产了几个编号

AddTime:生产时间

CodeValue:无效字段,没用到...

表的解读就这么多,现在来看一组存储过程:

 

ALTER proc [dbo].[LockCodeNoProc] --(@CodeCate nvarchar(50), @IsSuccess bit=0 output)asdeclare @currentYear as int declare @currentMonth as int declare @currentDay as int declare @count as intdeclare @CodeCount as intdeclare @flag as TimeStampdeclare @rowcount As int set @currentYear=DateName(year,GetDate()) set @currentMonth=DateName(month,GetDate()) set @currentDay=DateName(day,GetDate())begin transelect @count=count(1) from CM_Code where CodeYear=@currentYear and CodeMonth = @currentMonth and CodeDay=@currentDay and CodeCate=@CodeCateif @count=0begininsert into CM_Code(CodeCate,CodeYear,CodeMonth,CodeDay,CodeValue,CodeCount,AddTime) values(@CodeCate,@currentYear,@currentMonth,@currentDay,'',1,GETDATE())select CodeCount from  CM_Code where CodeYear=@currentYear and CodeMonth = @currentMonth and CodeDay=@currentDay and CodeCate=@CodeCateendelsebeginselect @count=CodeCount,@flag=VersionNum from CM_Code where CodeYear=@currentYear and CodeMonth = @currentMonth and CodeDay=@currentDay and CodeCate=@CodeCate--waitfor delay '00:00:10'  --可用于模拟并发update CM_Code set CodeCount=@count+1 where VersionNum=@flag and CodeYear=@currentYear and CodeMonth = @currentMonth and CodeDay=@currentDay and CodeCate=@CodeCateset @rowcount=@@ROWCOUNTselect CodeCount from  CM_Code where CodeYear=@currentYear and CodeMonth = @currentMonth and CodeDay=@currentDay and CodeCate=@CodeCateif @rowcount>0beginset @IsSuccess=1select @IsSuccessendelsebeginset @IsSuccess=0select @IsSuccessendendcommit tran
View Code

 

调用这个存储过程,会返回当前分类今天生产的编号数量,

时间有限,不作过多解读,大家自行理解,

下面是C#代码:

public class GetCode    {        public static string GetCodeNo(Enum CodeCate)        {            PortalCodeModel M = new PortalCodeModel();            M = U_GetCode.GetCodeNo(CodeCate);            //--模拟发生了并发,需要等待,重复请求,最大请求次数为10次            int retry = 10;            while (!M.IsSuccess && retry > 0)            {                retry--;                GetCodeNo(CodeCate);            }            //            string code = GetCodeString(M.Result);            return code;        }        public static string GetCodeString(int CodeCount)        {            string initStr = DateTime.Now.ToString("yyyyMMdd");            int initLen = initStr.Length;            int Len = CodeCount.ToString().Length;            int MaxLen = 10;            string ling = string.Empty;            int TotalLen = initLen + Len;            if (TotalLen <= MaxLen)            {                switch (Len)                {                    case 1:ling = initStr + "0" + CodeCount.ToString();break;                    default: ling = initStr + CodeCount.ToString(); break;                }            }            return ling;        }    }
View Code

DAL层如下:

public static PortalCodeModel GetCodeNo(Enum CodeCate)        {            using (DataAccessBroker broker = DataAccessFactory.Instance())            {                PortalCodeModel M = new PortalCodeModel();                DataAccessParameterCollection parameters = new DataAccessParameterCollection();                parameters.AddWithValue("@CodeCate", CodeCate.ToString());                parameters.AddWithValue("@IsSuccess", ParameterDirection.ReturnValue);                DataSet ds = broker.FillCommandDataSet("LockCodeNoProc", parameters);                //                if (ds != null && ds.Tables.Count > 0)                {                    var Result = Convert.ToInt32(ds.Tables[0].Rows[0]["CodeCount"]);                    var Bol = (ds.Tables[1].Rows[0][0]).ToString();                    if (Bol == "True")                    {                        M.Result = Result;                        M.IsSuccess = true;                    }                    else                    {                        M.Result = Result;                        M.IsSuccess = false;                    }                }                return M;            }        }
View Code

枚举层如下:

///     /// 各个枚举的‘值’使用表名即可    ///     public enum CodeCateEnum    {        [Description("现场考察")]        Inspection,        [Description("非设计类过程评估")]        EvluationPros,        [Description("非设计类履约评估")]        EvluationPlan,    }
View Code

OK ,就这么多,太忙,就不做过多的演示了!

public class PortalCodeModel    {        public bool IsSuccess { get; set; }        public int Result { get; set; }    }

说明下:当返回 IsSuccess 为 False 时,及说明发生了并发,应执行重复请求。这里采用的方式是:重复请求十次,直至成功为止!

C# 代码执行的时候,当第一次执行存储过程,会异常,请自行处理!

谢谢!

你可能感兴趣的文章
使用JWT作为Spring Security OAuth2的token存储
查看>>
使用Redis作为Spring Security OAuth2的token存储
查看>>
【SOLVED】Linux使用sudo到出现输入密码提示延迟时间长
查看>>
springmvc转springboot过程中访问jsp报Whitelabel Error Page错误
查看>>
项目引入非配置的文件,打成war包后测试报错的可能原因
查看>>
Git学习笔记
查看>>
SpringBoot笔记
查看>>
让你的代码更优秀的 14 条建议
查看>>
不需要爬虫也能轻松获取 unsplash 上的图片
查看>>
痞子衡嵌入式:语音处理工具pzh-speech诞生记(2)- 界面构建(wxFormBuilder3.8.0)
查看>>
将博客搬至CSDN
查看>>
痞子衡嵌入式:利用i.MXRT1xxx系列ROM提供的FlexSPI driver API可轻松IAP
查看>>
痞子衡嵌入式:极易上手的可视化wxPython GUI构建工具(wxFormBuilder)
查看>>
痞子衡嵌入式:串口调试工具pzh-com诞生记(2)- 界面构建(wxFormBuilder3.8.0)
查看>>
elementUi源码解析(1)--项目结构篇
查看>>
自动遍历测试之Monkey工具
查看>>
Nmap扫描工具介绍
查看>>
算法笔记:递归、动态规划
查看>>
Pytest插件开发
查看>>
常用Windows 快捷键
查看>>