C# + 微软企业库(Microsoft.Enterprise.Library),实现Oracle字段自增的应用
在数据库设计中,常常需要一个唯一表示数据记录的字段,我们叫“标识字段”,这个字段往往用于表记录之间的关联,对于SQL Server的使用者来说,只要把一个int型字段设置成“自增”就可以了。但是Oracle没有“自增”字段,这篇文章谈谈Oracle实现字段自增长并用C#调用微软企业库来访问的运用。
一.建表
建立一个测试用的表Test结构如下
列名 类型 是否可为空 说明
ID NUMBER N 实现自增字段
A NUMBER Y 测试字段1
B VARCHAR2(50) Y 测试字段2
接下来我们要实现列ID的自增,并用企业库调用。
二.建立序列
建立一个名称为Test_SQL的序列,使用PL/SQL查看序列的属性如下:
SEQUENCE_OWNER ZHYUANSAN
SEQUENCE_NAME TEST_SQL
MIN_VALUE 1
MAX_VALUE 1E27
INCREMENT_BY 1
CYCLE_FLAG N
ORDER_FLAG N
CACHE_SIZE 20
三.建立触发器
建立触发器代码如下:
create or replace trigger Test_INSERT_trigger
before insert on Test
for each row
begin
select Test_SQL.nextval into :new.ID from dual;
end ;
四.使用企业库插入数据
这时,我们可以使用PL/SQL插入数据:
insert into test values(0,23,’bbb’);
这里虽然第一个字段插入的数据是0,但是触发器自动会给它赋自增字段的值。
1.企业库配置文件
使用微软的企业库,连接数据库配置文件这样写:
<configSections>
<section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data,Version= 2.0.0.0,Culture=neutral,PublicKeyToken=null"/>
</configSections>
<dataConfiguration defaultDatabase= "ORACLE"/>
<connectionStrings>
<add name="ORACLE" connectionString="Data Source=gis;User ID=ZHYUANSHAN;Password=123456;Unicode=True" providerName= "System.Data.OracleClient"/>
</connectionStrings>
2.创建数据库访问对象
public static Database db = DatabaseFactory.CreateDatabase();
3.插入记录代码
string strsql = "INSERT INTO TEST(0,:A,:B) ";
DbCommand cmd = db. GetSqlStringCommand(strsql);
db. AddInParameter (cmd, "A", DbType.Int32, 23);
db. AddInParameter (cmd, "B", DbType.String, ‘ddd’);
db.ExecuteNonQuery(cmd);
五.问题
上面已经实现了数据的插入,也实现了字段自增,但是还有个问题就是,当有两个表关联时,我希望插入一个表的数据后,能够返回自增字段的值,然后再把这个值插入到另外一个表,实现两个表的关联。
如何返回这个新插入的自增字段的值呢?
有人说直接再写一行代码执行SELECT Test_SQL.currval from dual来获取自增字段的值不就可以了吗?
实际这样调用是不行的,SELECT Test_SQL.currval from dual只能在使用currval.nextval的同一个会话中调用,否则会出现“序列(号)不存在”的错误。
六.实现返回自增标识字段值
要马上获取自增标识字段的值,有以下3中方法:
1.先取值再插入(不需要触发器)
先执行命令SELECT Test_SQL.nextval from dual,来获取标识的值,再把这个值作为参数插入到数据库。这样就不需要触发器了,但是导致编码变得复杂,要增加获取标识的代码,插入时也要多传一个参数。
获取标识字段值代码:
string strsql = "SELECT Test_SQL.nextval FROM dual";
DbCommand cmd = db. GetSqlStringCommand(strsql);
object ob = db. ExecuteScalar(cmd);
int id = Convert.ToInt32(ob);
插入记录代码
strsql = "INSERT INTO TEST(:ID,:A,:B) ";
cmd = db. GetSqlStringCommand(strsql);
db.AddInParameter(cmd, "ID", DbType.Int32, id);
db.AddInParameter(cmd, "A", DbType.Int32, 23);
db.AddInParameter(cmd, "B", DbType.String, ‘ddd’);
db.ExecuteNonQuery(cmd);
……继续插入关联表信息。
2.利用存储过程(不需要触发器)
我们可以把上面的逻辑放到存储过程中,虽然我们增加了存储过程的编写,但是外部调用方法就更接近SQL Server了。
存储过程代码:
CREATE OR REPLACE PROCEDURE InsertTest(A in number,B in nvarchar2,id out number)
as
BEGIN
SELECT test_seq.nextval into id from dual;
insert into test values(id,A,B);
END InsertTest;
外部调用代码:
int id = 0;
string strsql = "InsertTest";
DbCommand cmd = db.GetStoredProcCommand(strsql);
db.AddInParameter(cmd, "A", DbType.Int32, 23);
db.AddInParameter(cmd, "B", DbType.String, ‘ddd’);
db.AddOutParameter(cmd, "id", DbType.Int32, id);
db.ExecuteNonQuery(cmd);
id = Convert.ToInt32(db.GetParameterValue(cmd, "id"));
……继续插入关联表信息。
3.利用存储过程 + 触发器
我们可以利用触发器,这样插入的时候就不用传入id了。
触发器代码:
create or replace trigger Test_INSERT_trigger
before insert on Test
for each row
begin
select Test_SEQ.nextval into :new.ID from dual;
end ;
存储过程代码:
CREATE OR REPLACE PROCEDURE InsertTest (A in number,B in nvarchar2,id out number)
as
BEGIN
insert into test values(0,A,B);
SELECT test_seq.currval into id from dual;
END InsertTest;
外部调用代码:
int id = 0;
string strsql = "InsertTest";
DbCommand cmd = db.GetStoredProcCommand(strsql);
db.AddInParameter(cmd, "A", DbType.Int32, 23);
db.AddInParameter(cmd, "B", DbType.String, ‘ddd’);
db.AddOutParameter(cmd, "id", DbType.Int32, id);
db.ExecuteNonQuery(cmd);
id = Convert.ToInt32(db.GetParameterValue(cmd, "id"));
……继续插入关联表信息。
本文来自CSDN博客:http://blog.csdn.net/zhyuanshan/archive/2008/10/24/3137967.aspx