长期以来我一直用的是MSSQLServer/Access数据库通过NET访问MS自家的东西几乎没碰到过什么麻烦最近项目中要用Oracle作为数据库学习研究了一些NET访问Oracle的东西发现问题倒真的不少
SystemDataOracleClient和SystemDataOleDb命名空间
虽然通过这两个命名空间的类都可以访问Oracle数据库但和SQLServer类似的(SystemDataSqlClient命名空间的类效率要比SystemDataOleDb命名空间中的类高一些)SystemDataOracleClient命名空间中的类要比SystemDataOleDb命名空间的类效率高一些(这一点我没有亲自验证但大多数地方都会这么说而且既然专门为Oracle作的东西理论上也应该专门作过针对性的优化)
当然还有另一点就是从针对性上说SystemDataOracleClient要更好一些
比如数据类型SystemDataOleDbOleDbType枚举中所列的就没有SystemDataOracleClientOracleType枚举中的那些有针对性另外Oracle的Number类型如果数字巨大超出NET数据类型范围的情况中就必须使用SystemDataOracleClient中的专门类OracleNumber类型
好了不再赘述这两个的比较下面主要讨论SystemDataOracleClient命名空间中的类型即ADONETforOracleDataProvider(数据提供程序)
数据库连接
无论是SystemDataOleDb还是SystemDataOracleClient访问Oracle都需要在NET运行的机器(ASPNET中就是Web服务器)安装Oracle客户端组件(这一点是和MS的两种数据库不同的MS的东西安装MDAC:MicrosoftDataAccessComponent以上版本后就无须再安装SQLServer客户端或者Office软件就能访问)
SystemRequirements
()如用SystemDataOracleClient访问Oracle客户端组件版本应在OracleiClientRelease()以上版本MS只确保访问OracleOracleOraclei服务器时的情况MDAC以上
()如用SystemDataOleDb访问Oracle客户端组件版本以上或以上MDAC以上
如服务器为Oraclei以上客户端组件版本应为c
在NET运行的机器中安装Oracle客户端然后打开NetManager(Oraclei)/EasyConfig(Oraclei)按你以前的经验设置本地服务的映射(这里的服务名将用于数据库连接串)
SystemDataOracleClient中访问Oracle数据库的连接串是
UserID=用户名;Password=密码;DataSource=服务名
(上述为一般的连接串详细的连接串项目可以在SystemDataOracleClientOracleConnectionConnectionString属性的文档中找到)
SystemDataOleDb中的访问Oracle数据库的连接串是
Provider=MSDAORA;UserID=用户名;Password=密码;DataSource=服务名
Oracle中的数据类型
Oracle的数据类型和SQLServer相比要奇怪一些SQLServer的大多数据类型很容易找到NET中比较接近的类型Oracle中的类型就离NET类型远了许多毕竟Oracle是和Java亲近的数据库
number:数字类型一般是Number(MN)M是有效数字N是小数点后的位数(默认)这个是按十进制说的
nvarchar:可变长字符型(Unicode)这个比较像SQLServer的nvarchar(但不知Oracle为什么加了个)(去掉n为非Unicode的下同)
nchar:定长字符型(Unicode)
nclob:写作文的字段存储大量字符(Unicode)时用
date:日期类型比较接近SQLServer的datetime
Oracle中字段不能是bit或者bool之类的类型一般是number()代替的
和SQLServer一样在SQL命令中字符类型需要用单引号()隔开两个单引号()是单引号的字符转义(比如Imfat写入一个SQL命令是UPDATESET=Imfat)
比较特殊的是日期类型比如要写入::这个时刻需要如下写
UPDATESET=TIMESTAMP::
注意这里使用了TIMESTAMP关键字并使用单引号隔开另外请注意日期格式上面的格式是可识别的Oracle识别的格式没有SQLServer那般多这是和SQLServer不同的地方
顺便提一句Access中的日期类型是用井号(#)隔开的UPDATESET=#::#
访问Oracle过程/函数()
SQLServer作程序时经常使用存储过程Oracle里也可以使用过程还可以使用函数Oracle的过程似乎是不能有返回值的有返回值的就是函数了(这点有些像BASIC函数/过程区分的很细致SQLServer存储过程是可以有返回值的)
NET访问Oracle过程/函数的方法很类似于SQLServer
例如
OracleParameter[]parameters={
newOracleParameter(ReturnValueOracleTypeIntParameterDirectionReturnValuetrue
DataRowVersionDefaultConvertDBNull)
newOracleParameter(参数OracleTypeNVarChar)
newOracleParameter(参数OracleTypeDateTime)
newOracleParameter(参数OracleTypeNumber)
};
parameters[]Value=test;
parameters[]Value=DateTimeNow;
parameters[]Value=;//也可以是newOracleNumber();
OracleConnectionconnection=newOracleConnection(ConnectionString);
OracleCommandcommand=newOracleCommand(函数/程名connection);
commandCommandType=CommandTypeStoredProcedure;
foreach(OracleParameterparameterinparameters)
commandParametersAdd(parameter);
connectionOpen();
commandExecuteNonQuery();
intreturnValue=parameters[]Value;//接收函数返回值
connectionClose();
Parameter的DbType设定请参见SystemDataOracleClientOracleType枚举的文档比如Oracle数据库中Number类型的参数的值可以用NETdecimal或SystemDataOracleClientOracleNumber类型指定Integer类型的参数的值可以用NETint或OracleNumber类型指定等等
上面例子中已经看到函数返回值是用名为ReturnValue的参数指定的该参数为ParameterDirectionReturnValue的参数
访问Oracle过程/函数()
不返回记录集(没有SELECT输出)的过程/函数调用起来和SQLServer较为类似但如果想通过过程/函数返回记录集在Oracle中就比较麻烦一些了
在SQLServer中如下的存储过程
CREATEPROCEDUREGetCategoryBooks
(
@CategoryIDint
)
AS
SELECT*FROMBooks
WHERECategoryID=@CategoryID
GO
在Oracle中请按以下步骤操作
()创建一个包含有一个游标类型(一个数据库中只需作一次)
CREATEORREPLACEPACKAGETest
AS
TYPETest_CURSORISREFCURSOR;
ENDTest;
()过程
CREATEORREPLACEPROCEDUREGetCategoryBooks
(
p_CURSORoutTestTest_CURSOR这里是上面包中的类型输出参数
p_CatogoryIDINTEGER
)
AS
BEGIN
OPENp_CURSORFOR
SELECT*FROMBooks
WHERECategoryID=p_CatogoryID;
ENDGetCategoryBooks;
()NET程序中
OracleParametersparameters={
newOracleParameter(p_CURSOROracleTypeCURSORParameterDirectionOutputtrue
DataRowVersionDefaultConvertDBNull)
newOracleParameter(p_CatogoryIDOracleTypeInt)
};
parameters[]Value=;
OracleConnectionconnection=newOracleConnection(ConnectionString);
OracleCommandcommand=newOracleCommand(GetCategoryBooksconnection);
commandCommandType=CommandTypeStoredProcedure;
foreach(OracleParameterparameterinparameters)
commandParametersAdd(parameter);
connectionOpen();
OracleDataReaderdr=commandExecuteReader();
while(drRead())
{
//你的具体操作这个就不需要我教吧?
}
connectionClose();
另外有一点需要指出的是如果使用DataReader取得了一个记录集那么在DataReader关闭之前程序无法访问输出参数和返回值的数据