Database2Sharp生成的Enterprise Library架构对Oracle自动增长列字段的支持

自动增长的主键字段是个好东西,提供了一个比较有意义和可阅读的字段内容(相对GUID来说),插入的时候,不用管它的值,数据库自动追加;但它也是一个不好的东西,如果管理不好,可能会造成冲突。本文暂且不讨论其优劣,因为存在就是硬道理,很多时候,我们都是采用自增长字段的,特别是对于SqlServer数据开发来说。

 本文阐述一下在Database2Sharp(软件下载地址:http://www.iqidi.com/database2sharp.htm生成的Enterprise Library架构如何实现Oracle的自增长的支持。同时也会顺带说说对SqlServer、Access的实现。

 Database2Sharp生成的Enterprise Library架构其实对Oracle内置了对自增长序列的支持,在数据库访问层的基类BaseDAL中,我们看到下面的代码。

     /// <summary>

    /// 数据访问层的基类
    
/// </summary>
    public abstract class BaseDAL<T> : IBaseDAL<T> where T : BaseEntity, new()
    {
        
#region 构造函数

        
protected string tableName;//需要初始化的对象表名
        protected string primaryKey;//数据库的主键字段名
        protected string sortField = "ID";//排序字段
        private bool isDescending = false;//

        
protected string selectedFields = " * ";//选择的字段,默认为所有(*)
        private string seqField = "";//指定那个字段是用序列来控制它的值的,一般为主键
        private string seqName = "";//指定的序列名称,建议规则为:SEQ_表名称
        
        
/// <summary>
        
/// 指定那个字段是用序列来控制它的值的,一般为主键
        
/// </summary>
        public string SeqField
        {
            
get { return seqField; }
            
set { seqField = value; }
        }

        
/// <summary>
        
/// 指定的序列名称,建议规则为:SEQ_表名称
        
/// </summary>
        public string SeqName
        {
            
get { return seqName; }
            
set { seqName = value; }
        }


这段代码定义了两个属性,一个是序列字段名称(一般是主键,如ID),一个是我们为该字段指定的序列对象名称,我们这里建议的名称是"SEQ_表名称",当然也可以使用任意的名称,合理统一就可以了。这两个属性在基类不需要修改,只需要在具体的数据访问对象(如数据访问层中的Customer类)构造函数中,指定序列字段和序列对象即可。

下面我们看看表盒序列的脚本代码,例如我创建一个客户表,其字段ID为自增序列,我的创建脚本是。

 create table ALL_CUSTOMER

(
  ID          NUMBER not null,
  USERNUMBER  VARCHAR2(50),
  NAME        VARCHAR2(50),
  TYPE        VARCHAR2(50),
  AREA        VARCHAR2(50),
  COMPANY     VARCHAR2(50),
  ADDRESS     VARCHAR2(50),
  TELEPHONE1  VARCHAR2(50),
  TELEPHONE2  VARCHAR2(50),
  TELEPHONE3  VARCHAR2(50),
  TELEPHONE4  VARCHAR2(50),
  TELEPHONE5  VARCHAR2(50),
  CREATEDATE  DATE,
  SHOP_ID     VARCHAR2(50),
  NOTE        VARCHAR2(255),
  LASTUPDATED DATE,
  
constraint PK_ALL_CUSTOMER primary key (ID)
);

create sequence SEQ_ALL_CUSTOMER
minvalue 1
maxvalue 999999999999999999999999999
start with 1220
increment by 1
cache 20;

commit;

 

注意SEQ_ALL_CUSTOMER就是序列对象名称,那么我们再插入的时候,应该如何写入序列字段的值,并且获得新的值作为返回值的呢?

在BaseDAL中,有一个Insert2的方法,是专门处理 自增序列函数,并且返回创建记录的自增字段的值的,我们来看看其源码。

         /// <summary>

        /// 添加记录
        
/// </summary>
        
/// <param name="recordField">Hashtable:键[key]为字段名;值[value]为字段对应的值</param>
        
/// <param name="targetTable">需要操作的目标表名称</param>
        
/// <param name="trans">事务对象,如果使用事务,传入事务对象,否则为Null不使用事务</param>
        public int Insert2(Hashtable recordField, string targetTable, DbTransaction trans)
        {
            
int result = -1;
            
string fields = ""// 字段名
            string vals = ""// 字段值
            if (recordField == null || recordField.Count < 1)
            {
                
return result;
            }

            List<OracleParameter> paramList = new List<OracleParameter>();
            IEnumerator eKeys = recordField.Keys.GetEnumerator();

            
while (eKeys.MoveNext())
            {
                
string field = eKeys.Current.ToString();
                fields += field + ",";
                
if (!string.IsNullOrEmpty(seqField) && !string.IsNullOrEmpty(seqName)
                    
&& (field == seqField))
                {
                    vals += string.Format("{0}.NextVal,", seqName);
                }
                
else
                {
                    vals += string.Format(":{0},", field);
                    
object val = recordField[eKeys.Current.ToString()];
                    paramList.Add(new OracleParameter(":" + field, val));
                }
            }

            fields = fields.Trim(',');//除去前后的逗号
            vals = vals.Trim(',');//除去前后的逗号
            string sql = string.Format("INSERT INTO {0} ({1}) VALUES ({2})", targetTable, fields, vals);

            Database db = DatabaseFactory.CreateDatabase();
            DbCommand command = db.GetSqlStringCommand(sql);
            command.Parameters.AddRange(paramList.ToArray());

            
if (trans != null)
            {
                db.ExecuteNonQuery(command, trans);

                sql = string.Format("SELECT {0}.Currval ID From Dual", seqName);
                command = db.GetSqlStringCommand(sql);
                result = Convert.ToInt32(db.ExecuteScalar(command, trans).ToString());
            }
            
else
            {
                db.ExecuteNonQuery(command);

                sql = string.Format("SELECT {0}.Currval ID From Dual", seqName);
                command = db.GetSqlStringCommand(sql);
                result = Convert.ToInt32(db.ExecuteScalar(command).ToString());
            }

            
return result;
        }

 

其中我们判断是否有自增序列ID和其名称(非空字符),如果有则使用这段代码,来写入自增序列的下一个值NextVal(新增值),作为这个字段的值。

vals += string.Format("{0}.NextVal,", seqName); 

 如果要返回插入的自增序列值,那么我们使用序列对象的Currval 就可以了。下面是返回插入的字段内容。

sql = string.Format("SELECT {0}.Currval ID From Dual", seqName); 

这样对于写入新的自增长值并返回就实现了。


对SqlServer和Access自增长字段的支持 

对于SqlServer,实现自增长字段就更加方便了,由于没有Oracle序列对象那么麻烦,所以只需要在具体的数据库访问对象中,构建写入字段的Hash表中,忽略该字段就可以了(代码已经自动生成,不用管理的)。其返回刚刚插入的自增内容,则在插入的语句后面增加一条语句就可以了,语句如下。

 SELECT SCOPE_IDENTITY()

对于Access的数据库,原理和SqlServer一样,不过需要返回刚刚插入的自增长值的时候,使用这段语句就可以了。

 SELECT @@IDENTITY

 对于SqlServer和Access,只要设计好数据库的自增字段,自动生成的代码中,数据访问类是不用修改任何信息,就可以完美支持自增序列。

 

posted on 2009-10-21 20:17  伍华聪  阅读(2962)  评论(4编辑  收藏  举报

导航