自动增长的主键字段是个好东西,提供了一个比较有意义和可阅读的字段内容(相对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,只要设计好数据库的自增字段,自动生成的代码中,数据访问类是不用修改任何信息,就可以完美支持自增序列。

标签: none

添加新评论