ODP.Net Sql的参数传递方法
Oracle为dotNet开发人员提供了全新的开发包ODP.NET,ODP.NET是为微软dotNet应用程序所提供的一套高效的访问Oracle数据库开发包。正是由于它的高效性,使用范围比较广。自然而然园子里面关于此的话题很多。这里我就切身实践谈谈ODP的使用。
第一次听说ODP也是在做项目改善速度的时候。历史回顾:接手某大型项目后,老大让我负责了一个很复杂的逻辑程序---说白了就是算钱。逻辑太复杂了,看老代码都是03年以前的,而且中间改过好几个版本。这稍微改错一个地,客户就要么多收钱,要么就亏钱。说实在压力山大。刚开始在老的基础上改过一段时间,发现这程序越改越比牛车还慢。10万数据要1个半小时。实际使用将有1000万数据,客户要求1小时以内。这如何是好?最后实在没办法,重写,分成常驻程序。想法有了,加班加点,总算是改造成功了!拿去运行,速度只提升了一个数量级。后来公司高手推荐用ODP。由于没用过,这问题接二连三出现。
ODP使用常见问题及解决方案
1,ODP版本与开发端的Oracle客户端版本不一致。
用select * from v$version;一查,我们服务器用的是11g 11.2.0.1.0,而我本地用的客户端是10g的。怕出问题,只好卸了10g,配上11g的客户端(Oracle的卸载也有不少学问,不知道的网上有很多资料)。版本是对了,可是客户端里面居然没带ODP.Net(我表示无语)。只好上官网下载,找了半天就是没有这11.2.0.1.0的ODP版本,这Oracle太坑人吧。这如何是好,客户已经在用这个版本了。人家上百台客户端总不可能为了这个全给升级吧。最后经过讨论把这程序放服务器端,在服务器端装个11.2.0.1.2的客户端版本。这回总算是同一版本了。
2,开发IDE VS 2005及以上
我们这项目都是用的Net 1.1+Vs 2003。在引用Oracle.DataAccess.dll类库时出错,加上错误信息又是日文。鬼才知道是啥意思。找个日本朋友看看也不明白啥意思。难题不断。看Oracle官网,10g都用到Vs 2005了。我想应该是开发IDE版本问题,就用Vs 2005试了下,结果正常引用。还好新做的程序是单独的,没辙只好将程序给升级到.Net 2.0。
3,ODP是区分32/64位的
以上的问题总算都解决了,然后查了点ODP使用,感觉和System.Data.OracleClient的使用差不多。就三下五除二改造完了,仔细测试了一通发现没问题,就发过去测试了。本想每晚11,12点下班的日子总算是要结束了,总算可以早点回去安心睡觉了。正要走人,客户一个电话@ODP无法使用,抛异常了!今晚必须解决!!@。天咋这么黑啊!经过百般调查,原来服务器是64位的------天咋越来越黑了!服务端64位,天啊!那得找个64位的开发电脑才行,还得下载个64位的ODP才行.............黑夜与我同行.......
无奈,找来台裸机,安装开发环境。上官网下64位ODP,这坑人的Oracle居然没有11.2.0.1.2版本的。只好下个11.2.0.3.0的版本了,最后总算是程序编译搞定。客户怕又出啥问题,就叫我陪他去测试服务器搞定这程序。又是各种安装卸载,最后总算是完事了。看看时间半夜了......淡定.......
ODP使用,虽然没长啥大经验,也算是一点点收获吧!下面讲讲实际如何使用Oracle.DataAccess.dll(要想以后更改数据底层方便,最好封装一个DB操作类)。
先来几句Sql:
INSERT INTO TS_ITEM(ITEM_CD) VALUES(:ITEM_CD)
SELECT ITEM_CD FROM TS_ITEM WHERE ITEM_CD BETWEEN :ITEMFROM AND :ITEMTO
这Sql是不是很像我在第二篇MSDAORA Sql的参数传递方法中写的一样。确实是如此,而且使用极其相似。Sql具体特点请参照MSDAORA Sql的参数传递方法。
应用举例:
/// <summary> /// 参数追加 /// </summary> /// <param name="valName"> 参数名</param> /// <param name="var">参数値</param> /// <param name="valType">参数类型</param> public static void AddDbParameter(string valName, object var, OracleDbType valType) { OracleParameter p = new OracleParameter(); p.ParameterName = valName; p.Direction = ParameterDirection.Input; p.OracleDbType = valType; p.IsNullable = true; p.Value = var; DbCommand.Parameters.Add(p); }
/// <summary> /// 数据取得 /// </summary> /// <param name="i_ItemFrom">項目From</param> /// <param name="i_ItemTO">項目To</param> /// <returns></returns> public static DataTable GetData(string i_ItemFrom,string i_ItemTO) { ODPParModel.PreProcess(); ODPParModel.PrepareDbSql(DBSql.ODPSelSql); ODPParModel.AddDbParameter("ITEMFROM", i_ItemFrom, OracleDbType.Varchar2); ODPParModel.AddDbParameter("ITEMTO", i_ItemTO, OracleDbType.Varchar2); return ODPParModel.GetDataSet("M_ITEM").Tables[0]; }
存储过程也是如此使用,只是CommandType不一样而已。
DbCommand.CommandType = CommandType.StoredProcedure;
总结下优缺点:
优点:1,能够充分利用Oracle数据库资源,速度极快。
2,在缓存没清除的情况下,此Sql数据库只需解析一次,再次执行此Sql时速度将更快。
3,传入参数顺序没要求,只要名字对应上就可以。
4,数据类型和Oracle数据库定义的完全一致。
缺点: 只能用于Oracle数据库
其他优缺点等大虾提供了。
附加ODP DBHelper类(精简版):
using System; using System.Collections.Generic; using System.Text; using System.Data; using Oracle.DataAccess.Client; using Oracle.DataAccess.Types; namespace DBPar.Models { public class ODPParModel { public static OracleConnection DbConnection; public static OracleTransaction transaction; public static OracleCommand DbCommand; public static OracleDataReader DbDataReader; public static OracleDataAdapter DbDataAdapter; /// <summary> /// DB连接 /// </summary> public static void PreProcess() { if (string.IsNullOrEmpty(DBConfig.ODP_DBConnectionString)) { DBConfig.Init(); } if (DbConnection == null) { try { DbConnection = new OracleConnection(DBConfig.ODP_DBConnectionString); DbConnection.Open(); } catch (InvalidOperationException) { throw new Exception("Config连接未设定" + DBConfig.ODP_DBConnectionString); } } if (transaction == null) { if (DbConnection.State != System.Data.ConnectionState.Open) { DbConnection.Open(); } transaction = DbConnection.BeginTransaction(); } } public static void EndProcess() { if (DbDataReader != null) { if (!DbDataReader.IsClosed) { DbDataReader.Close(); } DbDataReader = null; } if (DbCommand != null) { DbCommand.Dispose(); DbCommand = null; } if (transaction != null) { transaction.Commit(); transaction = null; } } public static void PrepareDbSql(string sql) { if (DbCommand != null) { DbCommand.Dispose(); } DbCommand = new OracleCommand(sql, DbConnection); } /// <summary> /// 参数追加 /// </summary> /// <param name="valName"> 参数名</param> /// <param name="var">参数値</param> /// <param name="valType">参数类型</param> public static void AddDbParameter(string valName, object var, OracleDbType valType) { OracleParameter p = new OracleParameter(); p.ParameterName = valName; p.Direction = ParameterDirection.Input; p.OracleDbType = valType; p.IsNullable = true; p.Value = var; DbCommand.Parameters.Add(p); } public static DataSet GetDataSet(string tablename) { DataSet ds = new DataSet(); OracleDataAdapter adapter = new OracleDataAdapter(); adapter.SelectCommand = DbCommand; adapter.Fill(ds, tablename); return ds; } public static int ExecuteDbUpdate() { return DbCommand.ExecuteNonQuery(); } } }
程序开发,终究是条无止境的路----