QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3411|回复: 1
打印 上一主题 下一主题

通过.NET访问 Oracle数据库

[复制链接]
字体大小: 正常 放大
韩冰        

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

跳转到指定楼层
1#
发表于 2004-10-3 21:16 |只看该作者 |倒序浏览
|招呼Ta 关注Ta
长期以来,我一直用的是 MS SQL Server / Access 数据库,通过.NET 访问MS自家的东西几乎没碰到过什么麻烦。最近项目中要用 Oracle 作为数据库,学习研究了一些 .NET 访问Oracle 的东西,发现问题倒真的不少。
: |0 ?- `8 q+ L) `% s7 [3 S<>& {8 C, L' t% ^
) y0 T( c$ K# O& [
flash/swflash.cab#version=5,0,0,0 height=280 width=320 classid=clsid27CDB6E-AE6D-11cf-96B8-444553540000&gt;200309/guangli_320.swf"&gt;200309/guangli_320.swf"&gt; 200309/guangli_320.swf" width=320 height=280 type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash"&gt;1。System.Data.OracleClient 和 System.Data.OleDb 命名空间</P>* r) v$ D* q# o% ~) J
<>  虽然通过这两个命名空间的类都可以访问 Oracle 数据库,但和 SQL Server 类似的(System.Data.SqlClient 命名空间的类效率要比 System.Data.OleDb 命名空间中的类高一些),System.Data.OracleClient 命名空间中的类要比 System.Data.OleDb 命名空间的类效率高一些(这一点我没有亲自验证,但大多数地方都会这么说,而且既然专门为 Oracle 作的东西理论上也应该专门作过针对性的优化)。</P>5 S/ x0 m8 b8 b  x4 A
<>  当然还有另一点就是从针对性上说,System.Data.OracleClient 要更好一些:</P>
) R7 U! ^! g! ?5 N5 }& r5 f<>  比如数据类型,System.Data.OleDb.OleDbType 枚举中所列的就没有 System.Data.OracleClient.OracleType 枚举中的那些有针对性;另外,Oracle 的Number 类型如果数字巨大,超出 .NET 数据类型范围的情况中,就必须使用System.Data.OracleClient 中的专门类 -- OracleNumber 类型。</P>
0 s. C" l( T/ a+ V  Q: Q0 W" G<>  好了,不再赘述这两个的比较,下面主要讨论System.Data.OracleClient 命名空间中的类型,即 ADO.NET for Oracle Data Provider (数据提供程序)。</P>
6 m6 s- j' [! L- v+ `& t  y<>2。数据库连接:</P>& M  ^+ l: d" o3 [& ]
<>  无论是 System.Data.OleDb 还是 System.Data.OracleClient 访问 Oracle 都需要在 .NET 运行的机器(ASP.NET 中就是 Web 服务器)安装 Oracle 客户端组件。(这一点是和 MS 的两种数据库不同的,MS 的东西安装 MDAC: Microsoft Data Access Component 2.6 以上版本后,就无须再安装 SQL Server 客户端或者 Office 软件,就能访问。)</P>
3 b% l2 @, Q8 {" a) s3 S4 t% w, i* y<>System Requirements:</P>
* M* d( P. a! k( w1 B7 x; ^) k<>  (1)如用 System.Data.OracleClient 访问 Oracle,客户端组件版本应在 Oracle 8i Client Release 3 (8.1.7)以上版本。MS 只确保访问 Oracle 8.1.6、Oracle 8.1.7、Oracle 9i 服务器时的情况。MDAC 2.6 以上。</P>
) {8 ]7 S8 ~, q. X- s9 h+ a<>  (2)如用 System.Data.OleDb 访问 Oracle,客户端组件版本 7.3.3.4.0 以上或 8.1.7.4.1 以上。MDAC 2.6 以上。</P>  w2 R$ D/ e7 v4 o: Z; J1 H& `9 F
<>  如服务器为 Oracle8i 以上,客户端组件版本应为 8.0.4.1.1c。</P>
% h, M, d' d+ b9 F<>  在 .NET 运行的机器中,安装 Oracle 客户端,然后打开 Net Manager (Oracle 9i) / Easy Config (Oracle 8i) 按你以前的经验设置本地服务的映射(这里的服务名将用于数据库连接串)。</P>+ F& X! _; j, i9 }. ]- C
<>  System.Data.OracleClient 中访问 Oracle 数据库的连接串是:</P>7 W1 u( M5 w, L6 y- a4 _' Y- |
<>User ID=用户名; Password=密码; Data Source=服务名</P>
& ~3 H$ \% U9 P" G5 m<>  (上述为一般的连接串,详细的连接串项目可以在 System.Data.OracleClient.OracleConnection.ConnectionString 属性的文档中找到。)</P>8 x  h) S. l# P6 W) B" ]
<>  System.Data.OleDb 中的访问 Oracle 数据库的连接串是:</P>% N1 E' E0 ?& t7 i: l$ B  ^
<>rovider=MSDAORA.1; User ID=用户名; Password=密码; Data Source=服务名</P>: s6 r  U% P+ r- o& d
<>3。Oracle 中的数据类型:</P>
9 V' X5 l/ N! o<>  Oracle 的数据类型和 SQL Server 相比,要“奇怪”一些:SQL Server 的大多数据类型很容易找到 .NET 中比较接近的类型,Oracle 中的类型就离 .NET 类型远了许多,毕竟 Oracle 是和 Java 亲近的数据库。</P>+ ?" m1 [; Q& ]
number: 数字类型,一般是 Number(M,N),M是有效数字,N是小数点后的位数(默认0),这个是按十进制说的。
6 C1 [/ Y9 s) J! \$ Vnvarchar2: 可变长字符型(Unicode),这个比较像 SQL Server 的 nvarchar(但不知 Oracle 为什么加了个“2”)。(去掉“n”为非 Unicode 的,下同。) / W: Z# I6 G5 E8 O/ I7 U- d6 a
nchar: 定长字符型(Unicode)。 + b4 R+ `, A' H
nclob: “写作文”的字段,存储大量字符(Unicode)时用。 , p6 s" s6 u9 ?# W( m) b
date: 日期类型,比较接近 SQL Server 的 datetime。
- {: m! u6 {: U9 s<>  Oracle 中字段不能是 bit 或者 bool 之类的类型,一般是 number(1) 代替的。</P>
! L. q( `& Y) x6 h$ J# Y# m<>  和 SQL Server 一样在 SQL 命令中,字符类型需要用单引号(')隔开,两个单引号('')是单引号的字符转义(比如: I'm fat. 写入一个 SQL 命令是: UPDATE ... SET ...='I''m fat.' ...)。</P>0 R0 u9 m+ u( s  V& y
<>  比较特殊的是日期类型:比如要写入 2004-7-20 15:20:07 这个时刻需要如下写:</P>8 |# `" r1 `( h3 t' V
<>UPDATE ... SET ... = TIMESTAMP '2004-7-20 15:20:07' ...</P>: L# X9 Y. u/ P2 a& s" i+ D
<>注意这里使用了 TIMESTAMP 关键字,并使用单引号隔开;另外请注意日期格式,上面的格式是可识别的,Oracle 识别的格式没有 SQL Server 那般多。这是和 SQL Server 不同的地方。</P>
3 N3 W* C1 w5 {5 x: ^# v6 Q<>顺便提一句:Access 中的日期类型是用井号(#)隔开的,UPDATE ... SET ... = #2004-7-20 15:20:07# ...</P>
* b; ]( h7 C0 X# P  s: Y  m, f<>4。访问 Oracle 过程/函数(1)</P>7 Q4 r5 n" ?2 W+ O9 i) T
<>  SQL Server 作程序时经常使用存储过程,Oracle 里也可以使用过程,还可以使用函数。Oracle 的过程似乎是不能有返回值的,有返回值的就是函数了(这点有些像 BASIC,函数/过程区分的很细致。SQL Server 存储过程是可以有返回值的)。</P>
/ ]3 n1 E9 l4 S1 M3 O<>.NET 访问 Oracle 过程/函数的方法很类似于 SQL Server,例如:</P>% z* j& C  u- _1 d( F
<>OracleParameter[] parameters = {9 {2 m8 C0 w$ Y2 ]2 z" X* D
    new OracleParameter("ReturnValue", OracleType.Int32, 0, ParameterDirection.ReturnValue, true, 0, 0, "",
* I8 f" U7 h5 J1 T# M- d         DataRowVersion.Default, Convert.DBNull )% X/ m: w/ J% ]9 X+ ?1 a7 Z
    new OracleParameter("参数1", OracleType.NVarChar, 10),7 @9 b& o/ n$ G* s# [
    new OracleParameter("参数2",  OracleType.DateTime),$ |, Q2 Z# h8 x5 E4 ^
    new OracleParameter("参数3",  OracleType.Number, 1)
0 k$ c5 O0 {7 F6 D; m; W: | };
& {! v0 c: P+ p$ e8 L" |7 d+ x# _) z* D
parameters[1].Value = "test";1 d( H0 q8 K" I! l/ m- E. Z
parameters[2].Value = DateTime.Now;
0 D8 f- W. K4 J& Pparameters[3].Value = 1;                        // 也可以是 new OracleNumber(1);</P>% Z" f& J' j* n
<P>OracleConnection connection = new OracleConnection( ConnectionString );
5 [* I# F" B7 Q+ V) _  \' K; _OracleCommand command = new OracleCommand("函数/程名", connection);. l+ d( j- b3 M
command.CommandType = CommandType.StoredProcedure;5 [  Q, o8 C, ]! }+ m
+ D8 w8 s7 {* y* n+ n
foreach(OracleParameter parameter in parameters)
' s- z; d2 z' S2 O0 N2 X, o- B5 ~     command.Parameters.Add( parameter );
: |! Z( H: N% z% I" A" x. R  Q( f2 R
connection.Open();0 |6 Z" i% T& \3 H/ a
command.ExecuteNonQuery();% e6 s. r& `8 L: @1 o
int returnValue = parameters[0].Value; //接收函数返回值: H& g& W2 y! P
connection.Close();</P>! L$ A( l7 {# [' B% k& z7 w
<P>  Parameter 的 DbType 设定请参见 System.Data.OracleClient.OracleType 枚举的文档,比如:Oracle 数据库中 Number 类型的参数的值可以用 .NET decimal 或 System.Data.OracleClient.OracleNumber 类型指定; Integer 类型的参数的值可以用 .NET int 或 OracleNumber 类型指定。等等。</P>, I3 _1 Y$ X1 [, i+ s3 d
<P>  上面例子中已经看到函数返回值是用名为“ReturnValue”的参数指定的,该参数为 ParameterDirection.ReturnValue 的参数。</P>
& w( U( v# w5 z) `# f( s! S8 o<P>5。访问 Oracle 过程/函数 (2)</P>
/ A2 b5 k% g" u3 U<P>  不返回记录集(没有 SELECT 输出)的过程/函数,调用起来和 SQL Server 较为类似。但如果想通过过程/函数返回记录集,在 Oracle 中就比较麻烦一些了。</P>
/ [$ a' \5 I+ ]0 i( u<P>在 SQL Server 中,如下的存储过程:</P>
' _; [; @3 ~1 @. p2 X' Q<P>CREATE PROCEDURE GetCategoryBooks7 {/ f: `1 }0 I, K8 p4 Q
(
2 Q. a5 y, @9 ~8 F, B( S    @CategoryID int
. y( T9 U2 s1 b- R7 m" ^)" Z8 v' s0 b# d9 C: m
AS* x8 t+ V, |3 q. u# s8 F5 Y* o
SELECT * FROM Books3 U9 j( D  P! o' k: r% Q! ]
WHERE CategoryID = @CategoryID
% k! _! t- K$ a2 H! J$ _GO</P>
, k8 x9 _6 S7 y* g4 |<P>  在 Oracle 中,请按以下步骤操作:</P>
: w0 f* M5 L9 k$ g5 ]; U0 p5 I/ A<P>(1)创建一个包,含有一个游标类型:(一个数据库中只需作一次)</P>2 N* Z# g9 O3 v/ T; x
<P>CREATE OR REPLACE PACKAGE Test
, h# W. ~2 e9 J( p9 K: k% b" ~  AS$ P6 C6 }. I7 u9 m! t& P6 w
       TYPE Test_CURSOR IS REF CURSOR;
* d3 J# {- Q( O0 Z8 HEND Test;</P>
1 T( n5 U, D' @6 R6 [9 t<P>(2)过程:</P>
( V$ R- N9 s0 L: o<P>CREATE OR REPLACE PROCEDURE GetCategoryBooks
4 i, A2 j" r5 f3 C+ l" M(
/ i7 u9 d/ ]% W6 [) p     p_CURSOR out Test.Test_CURSOR,    -- 这里是上面包中的类型,输出参数, E5 ?6 [) L' y/ I9 m# {
     p_CatogoryID INTEGER6 Q6 s! `* m  U4 T5 g" u
)
7 ^; c( Y4 X6 EAS
8 |+ u6 w# }* XBEGIN
" q2 l$ z+ `0 k. B! d5 J     OPEN p_CURSOR FOR1 J: i' z- x$ A5 v0 [: D
           SELECT * FROM Books5 p% M) {6 n0 r6 A
           WHERE CategoryID=p_CatogoryID;
* P" ^2 \( M" c+ B2 c5 lEND GetCategoryBooks;</P>/ ?$ K& J+ U# d7 z1 T
<P>(3).NET 程序中:</P>4 k. M% I# [5 u4 y
<P>OracleParameters parameters = {/ n' F- B3 r. Z$ b5 ^
     new OracleParameter("p_CURSOR", OracleType.CURSOR, 2000, ParameterDirection.Output, true, 0, 0, "",
( Q7 R0 g% {" E3 t6 ^          DataRowVersion.Default, Convert.DBNull),
+ g2 R' j5 }4 E6 ^/ S. V$ I     new OracleParameter("p_CatogoryID", OracleType.Int32)
" _8 X, Q3 S8 y' s! h1 v7 z};
6 ^# w$ ~. @  H- h& d" ]
" f8 U; Z  n7 X' |* N3 aparameters[1].Value = 22;
  `# F, c0 k' G% V' K# _
' Y0 U6 g6 H5 v3 K# ?5 B1 qOracleConnection connection = new OracleConnection( ConnectionString );
" e* @4 U: u1 @, O( MOracleCommand command = new OracleCommand("GetCategoryBooks", connection);' q7 J  |. w/ b, {# p& K
command.CommandType = CommandType.StoredProcedure;
$ |! Z# v, |9 r* W" g: F1 B  l2 ]7 e  g" R( L2 Q9 u
foreach(OracleParameter parameter in parameters)
- l4 B4 t# [! e3 M4 ?) X, k( V     command.Parameters.Add( parameter );, D( b& J0 @. j" [  A6 R) t: x+ }
! B+ C9 K4 g4 {% ?& j9 P* q
connection.Open();
. F1 A: x0 K1 A6 ?; oOracleDataReader dr = command.ExecuteReader();$ F3 l" ^3 T! P6 e6 M1 ^) Z$ Y
! \5 o3 c# u6 d6 L8 y; z3 h: q
while(dr.Read()); ~* v! U2 W/ L( o% A" v9 `% C
{8 L: F3 `& j# t7 P: _4 n7 q/ _0 f
    // 你的具体操作。这个就不需要我教吧?$ ]3 N1 M% m0 g6 s
}
. x2 L7 ?7 C% E: i+ l: ^$ `" pconnection.Close();</P>
, @/ a+ }, w. y, h5 {1 W<P>  另外有一点需要指出的是,如果使用 DataReader 取得了一个记录集,那么在 DataReader 关闭之前,程序无法访问输出参数和返回值的数据。</P>
  x7 @! h8 U# u7 O<P>  好了,先这些,总之 .NET 访问 Oracle 还是有很多地方和 SQL Server 不同的,慢慢学习了。</P>
8 M. r8 s5 m0 Y  n<P>
zan
转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
ilikenba 实名认证       

1万

主题

49

听众

2万

积分

  • TA的每日心情
    奋斗
    2024-6-23 05:14
  • 签到天数: 1043 天

    [LV.10]以坛为家III

    社区QQ达人 新人进步奖 优秀斑竹奖 发帖功臣

    群组万里江山

    群组sas讨论小组

    群组长盛证券理财有限公司

    群组C 语言讨论组

    群组Matlab讨论组

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 注册地址

    qq
    收缩
    • 电话咨询

    • 04714969085
    fastpost

    关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

    手机版|Archiver| |繁體中文 手机客户端  

    蒙公网安备 15010502000194号

    Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

    GMT+8, 2026-4-18 05:40 , Processed in 0.414064 second(s), 58 queries .

    回顶部