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

 

 

 

posted @ 2013-03-20 18:09  李蒙强  阅读(2206)  评论(2编辑  收藏  举报