C# 调用 Oracle 是如此尴尬

>System.Data.OracleClient.dll —— .Net 自带的 已经 过时作废。

>要链接 Oracle 服务器,必须在 本机安装 Oracle 客户端 —— 而 SQLServer 不需要安装客户端。

win32_11gR2_client.zip(652M)

win64_11gR2_client.zip(587M)

>Oracle.DataAccess.dll—— Oracle 官方 提供的.Net 程序集【在安装目录 ODP.NET 中】。

Oracle.DataAccess.dll  严格区分 x32、x64 —— 程序集 不是 AnyCPU。

x32 客户端 只包括 x32 的 Oracle.DataAccess.dll。

x64 客户端 只包括 x64 的 Oracle.DataAccess.dll。

发布程序的时候,就很容易在这个地方 出现问题。

>Oracle.ManagedDataAccess.dll —— Oracle 官方 提供的.Net  程序集

支持 AnyCPU

不需要安装 600M 的客户端

Oracle.ManagedDataAccess —— 你值得拥有。

>Oracle.DataAccess.dll  和  Oracle.ManagedDataAccess.dll  用法完全一样。

支持的 SQL脚本语法一样。

SQL 脚本 不能以 分号 结尾。

一样的:这也不支持,那也不支持。

C# 调用 Oracle 语法限制

>Oracle 不支持 自增主键 —— 自增主键 需要使用 触发器。

>Oracle 表名,字段名 不能超过30个字符。

>脚本 参数化,    关键符为 : —— SQLServer 关键符为 @

>脚本 名称区域, 关键符为 "表名"."字段名" —— SQLServer 关键符为 [表名].[字段名]

警告:脚本中 不建议 将 数据库名、表名、字段名 用 引号括起来 —— 后果很严重。

>支持 多条 修改语句 同时执行:

  1. BEGIN
  2.  
  3. UPDATE TB_Test SET Name='INK';
  4.  
  5. DELETE TB_Test WHERE Name='INK';
  6.  
  7. INSERT INTO TB_Test(Name) VALUES('INK');
  8.  
  9. END;

>不支持 多条 查询语句,得到 DataSet —— 支持 单一查询得到 DataSet。

>支持 ExecuteScalar —— 但是 执行脚本 必须是 单条脚本。

>不支持 插入&查询 自增列—— SQLServer 支持 INSERT INTO…. SELECT@@IDENTITY

警告:即使使用 触发器 实现 自增ID,以下语法也 无法执行

  1. BEGIN
  2.  
  3. INSERT INTO TB_Test(Name) VALUES('INK'); --先执行 插入
  4.  
  5. SELECT MAX(ID) FROMTB_Test; --再执行 查询 最大ID
  6.  
  7. END

C# 调用 Oracle 的死结 在于:不支持 多条 非影响SQL脚本同时执行。

有鉴于此,自己随手写了一个OracleHelper.cs

>之前 Oracle 脚本, 自然是 支持的。

>多条 Oracle 脚本,用 ; 分割 —— 即能支持 多条SQL脚本。

>避开了 SQLServer 迁移 Oracle 过程中,出现的脚本不兼容。

>多条SQL脚本将自动开启 数据库事务,确保 绝对正确。

>支持 多条SELECT返回 多DataTable的 DataSet。

>支持 插入&查询自增列(触发器实现的 自增列)

Oracle 全托管程序集 Oracle.ManagedDataAccess.dll 

>不再需要安装 600M 的客户端,只需要 单纯引用程序集 就行。

>Oracle.ManagedDataAccess.dll  只是简化了 安装部署,支持 AnyCPU。

>测试通过,但是 功能和 Oracle.DataAccess.dll 功能一样:

.net C# SqlHelper for Oracle

适用于Oracle的sqlhelper

需要使用ODP.Net,引用Oracle.DataAccess.dll  推荐安装ODAC

代码如下:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Reflection;
  7. using System.Data;
  8. using System.Configuration;
  9. using Oracle.DataAccess.Client;
  10.  
  11. namespace DAL
  12. {
  13. public static class SqlHelper
  14. {
  15. #region 样本
  16. //标准连接-SSPI
  17. private static readonly string defaultConnectString = "Data Source=ORCL;Integrated Security=SSPI;";
  18. //标准连接
  19. //private static readonly string defaultConnectString = "Data Source=ORCL;User Id=UPDM;Password=1234;";
  20. //标准链接
  21. //private static readonly string defaultConnectString = "Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=orcl)));User Id=system;Password=1234;";
  22. #endregion
  23. #region 变量
  24.  
  25. private static OracleConnection _con = null;
  26. public static string _constr = ConfigurationManager.ConnectionStrings["orcl"].ToString();
  27.  
  28. #endregion
  29.  
  30. #region 属性
  31.  
  32. public static string constr
  33. {
  34. get
  35. {
  36. if (_constr == null||_constr.Equals(String.Empty))
  37. {
  38. _constr = defaultConnectString;
  39. }
  40. return _constr;
  41. }
  42. set
  43. {
  44. _constr = value;
  45. }
  46. }
  47.  
  48. /// <summary>
  49. /// 获取或设置数据库连接对象
  50. /// </summary>
  51. public static OracleConnection Con
  52. {
  53. get
  54. {
  55.  
  56. if (SqlHelper._con == null)
  57. {
  58. SqlHelper._con = new OracleConnection();
  59. }
  60. if (SqlHelper._con.ConnectionString == null || SqlHelper._con.ConnectionString.Equals(string.Empty))
  61. {
  62. SqlHelper._con.ConnectionString = SqlHelper.constr;
  63. }
  64. return SqlHelper._con;
  65. }
  66. set
  67. {
  68. SqlHelper._con = value;
  69. }
  70. }
  71. #endregion
  72.  
  73. #region 方法
  74.  
  75. /// <summary>
  76. /// 执行并返回第一行第一列的数据库操作
  77. /// </summary>
  78. /// <param name="commandText">Sql语句或存储过程名</param>
  79. /// <param name="commandType">Sql命令类型</param>
  80. /// <param name="param">Oracle命令参数数组</param>
  81. /// <returns>第一行第一列的记录</returns>
  82. public static int ExecuteScalar(string commandText, CommandType commandType, params OracleParameter[] param)
  83. {
  84. int result = 0;
  85. try{
  86. using (OracleCommand cmd = new OracleCommand(commandText, SqlHelper.Con))
  87. {
  88. try
  89. {
  90. cmd.CommandType = commandType;
  91. if (param!=null)
  92. {
  93. cmd.Parameters.AddRange(param);
  94. }
  95. SqlHelper.Con.Open();
  96. string x = cmd.CommandText;
  97. result = Convert.ToInt32(cmd.ExecuteScalar());
  98. }
  99. catch
  100. {
  101. result = -1;
  102. }
  103. }
  104. }
  105. finally
  106. {
  107. if (SqlHelper.Con.State != ConnectionState.Closed)
  108. {
  109. SqlHelper.Con.Close();
  110. }
  111. }
  112. return result;
  113. }
  114.  
  115. /// <summary>
  116. /// 执行不查询的数据库操作
  117. /// </summary>
  118. /// <param name="commandText">Oracle语句或存储过程名</param>
  119. /// <param name="commandType">Oracle命令类型</param>
  120. /// <param name="param">Oracle命令参数数组</param>
  121. /// <returns>受影响的行数</returns>
  122. public static int ExecuteNonQuery(string commandText, CommandType commandType, params OracleParameter[] param)
  123. {
  124. int result = 0;
  125. try
  126. {
  127. using (OracleCommand cmd = new OracleCommand(commandText, SqlHelper.Con))
  128. {
  129. try
  130. {
  131. cmd.CommandType = commandType;
  132. if (param!=null)
  133. {
  134. cmd.Parameters.AddRange(param);
  135. }
  136. SqlHelper.Con.Open();
  137. result = cmd.ExecuteNonQuery();
  138. }
  139. catch
  140. {
  141. result = -1;
  142. }
  143. }
  144. }
  145. finally
  146. {
  147. if (SqlHelper.Con.State != ConnectionState.Closed)
  148. {
  149. SqlHelper.Con.Close();
  150. }
  151. }
  152. return result;
  153. }
  154.  
  155. /// <summary>
  156. /// 获取数据表
  157. /// </summary>
  158. /// <param name="commandText">select命令</param>
  159. /// <param name="param">参数表</param>
  160. /// <returns></returns>
  161. public static DataTable GetDataTable(string commandText,params OracleParameter[] param)
  162. {
  163. DataTable result = new DataTable();
  164. try
  165. {
  166. using (OracleCommand cmd = new OracleCommand(commandText, SqlHelper.Con))
  167. {
  168. cmd.Parameters.AddRange(param);
  169. try {
  170. OracleDataAdapter adapter = new OracleDataAdapter(cmd);
  171. adapter.Fill(result);
  172. }
  173. catch
  174. {
  175. result = null;
  176. }
  177. }
  178. }
  179. finally
  180. {
  181. if (SqlHelper.Con.State != ConnectionState.Closed)
  182. {
  183. SqlHelper.Con.Close();
  184. }
  185. }
  186. return result;
  187. }
  188.  
  189. public static int GetNextValueInSequence(string sequenceName)
  190. {
  191. if (ExecuteScalar("select count(*) from user_objects where OBJECT_NAME=:seqName", CommandType.Text, new OracleParameter(":seqName",sequenceName)) > 0)
  192. {
  193. return ExecuteScalar("select " + sequenceName + ".nextval from dual", CommandType.Text);
  194. }
  195. else
  196. {
  197. return -1;
  198. }
  199.  
  200. }
  201.  
  202. /// <summary>
  203. /// 事务模式执行多行非查询语句
  204. /// </summary>
  205. /// <param name="commandText">sql语句</param>
  206. /// <param name="param">参数</param>
  207. /// <returns>受影响行数</returns>
  208. public static int ExecuteNonQueryTransaction(string commandText, List<OracleParameter[]> param)
  209. {
  210. int result = 0;
  211. try
  212. {
  213. using (OracleCommand cmd = new OracleCommand(commandText, SqlHelper.Con))
  214. {
  215. SqlHelper.Con.Open();
  216. cmd.Transaction = cmd.Connection.BeginTransaction();
  217. try
  218. {
  219. foreach (OracleParameter[] par in param)
  220. {
  221. cmd.Parameters.Clear();
  222. cmd.Parameters.AddRange(par);
  223. result += cmd.ExecuteNonQuery();
  224. }
  225. cmd.Transaction.Commit();
  226. }
  227. catch
  228. {
  229. result = -1;
  230. try
  231. {
  232. cmd.Transaction.Rollback();
  233. }
  234. catch
  235. {
  236. result = -2;
  237. }
  238. }
  239. }
  240. }
  241. finally
  242. {
  243. if (SqlHelper.Con.State != ConnectionState.Closed)
  244. {
  245. SqlHelper.Con.Close();
  246. }
  247. }
  248. return result;
  249. }
  250.  
  251. /// <summary>
  252. /// 执行返回一条记录的泛型对象
  253. /// </summary>
  254. /// <typeparam name="T">泛型类型</typeparam>
  255. /// <param name="reader">只进只读对象</param>
  256. /// <returns>泛型对象</returns>
  257. private static T ExecuteDataReader<T>(IDataReader reader)
  258. {
  259. T obj = default(T);
  260. try
  261. {
  262. Type type = typeof(T);
  263. obj = (T)Activator.CreateInstance(type);//从当前程序集里面通过反射的方式创建指定类型的对象
  264. //obj = (T)Assembly.Load(SqlHelper._assemblyName).CreateInstance(SqlHelper._assemblyName + "." + type.Name);//从另一个程序集里面通过反射的方式创建指定类型的对象
  265. PropertyInfo[] propertyInfos = type.GetProperties();//获取指定类型里面的所有属性
  266. foreach (PropertyInfo propertyInfo in propertyInfos)
  267. {
  268. for (int i = 0; i < reader.FieldCount; i++)
  269. {
  270. string fieldName = reader.GetName(i);
  271. if (fieldName.ToLower() == propertyInfo.Name.ToLower())
  272. {
  273. object val = reader[propertyInfo.Name];//读取表中某一条记录里面的某一列
  274. if (val != null && val != DBNull.Value)
  275. {
  276. Type valType = val.GetType();
  277.  
  278. if (valType == typeof(float) || valType == typeof(double) || valType== typeof(decimal))
  279. {
  280. propertyInfo.SetValue(obj, Convert.ToDouble(val), null);
  281. }
  282. else if (valType == typeof(int))
  283. {
  284. propertyInfo.SetValue(obj, Convert.ToInt32(val), null);
  285. }
  286. else if (valType == typeof(DateTime))
  287. {
  288. propertyInfo.SetValue(obj, Convert.ToDateTime(val), null);
  289. }
  290. else if (valType == typeof(string))
  291. {
  292. propertyInfo.SetValue(obj, Convert.ToString(val), null);
  293. }
  294. }
  295. break;
  296. }
  297. }
  298. }
  299. }
  300. catch
  301. {
  302. throw;
  303. }
  304. return obj;
  305. }
  306.  
  307. /// <summary>
  308. /// 执行返回一条记录的泛型对象
  309. /// </summary>
  310. /// <typeparam name="T">泛型类型</typeparam>
  311. /// <param name="commandText">Oracle语句或存储过程名</param>
  312. /// <param name="commandType">Oracle命令类型</param>
  313. /// <param name="param">Oracle命令参数数组</param>
  314. /// <returns>实体对象</returns>
  315. public static T ExecuteEntity<T>(string commandText, CommandType commandType, params OracleParameter[] param)
  316. {
  317. T obj = default(T);
  318. try
  319. {
  320. using (OracleCommand cmd = new OracleCommand(commandText, SqlHelper.Con))
  321. {
  322. cmd.CommandType = commandType;
  323. cmd.Parameters.AddRange(param);
  324. SqlHelper.Con.Open();
  325. OracleDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
  326. while (reader.Read())
  327. {
  328. obj = SqlHelper.ExecuteDataReader<T>(reader);
  329. }
  330. }
  331. }
  332. finally
  333. {
  334. if (SqlHelper.Con.State != ConnectionState.Closed)
  335. {
  336. SqlHelper.Con.Close();
  337. }
  338. }
  339. return obj;
  340. }
  341.  
  342. /// <summary>
  343. /// 执行返回多条记录的泛型集合对象
  344. /// </summary>
  345. /// <typeparam name="T">泛型类型</typeparam>
  346. /// <param name="commandText">Oracle语句或存储过程名</param>
  347. /// <param name="commandType">Oracle命令类型</param>
  348. /// <param name="param">Oracle命令参数数组</param>
  349. /// <returns>泛型集合对象</returns>
  350. public static List<T> ExecuteList<T>(string commandText, CommandType commandType, params OracleParameter[] param)
  351. {
  352. List<T> list = new List<T>();
  353. try
  354. {
  355. using (OracleCommand cmd = new OracleCommand(commandText, SqlHelper.Con))
  356. {
  357. try
  358. {
  359. cmd.CommandType = commandType;
  360.  
  361. if (param != null)
  362. {
  363. cmd.Parameters.AddRange(param);
  364. }
  365. SqlHelper.Con.Open();
  366.  
  367. OracleDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
  368.  
  369. while (reader.Read())
  370. {
  371. T obj = SqlHelper.ExecuteDataReader<T>(reader);
  372. list.Add(obj);
  373. }
  374. }
  375. catch (Exception ex)
  376. {
  377. list = null;
  378. }
  379. }
  380. }
  381. finally
  382. {
  383. if (SqlHelper.Con.State != ConnectionState.Closed)
  384. {
  385. SqlHelper.Con.Close();
  386. }
  387. }
  388. return list;
  389. }
  390.  
  391. #endregion
  392. }
  393. }

C# 调用 Oracle的更多相关文章

  1. 电脑上不安装Oracle时,C# 调用oracle数据库,Oracle客户工具

    Oracle的安装包通常都比较大,安装又比较费时,而且如果安装过程中不幸出错,各种蛋疼,即便是安装过N遍的老手,有时候安装起来也觉得挺烦.而工作中,通常服务器上面安装oracle就可以了,我们本地电脑 ...

  2. MyBatis调用Oracle存储过程

    MyBatis调用Oracle存储过程 1.无输入和输出参数的存储过程 2.带有输入和输出参数的存储过程 3.返回游标的存储过程 mybatis中的配置文件代码 <resultMap type= ...

  3. java下实现调用oracle的存储过程和函数

    在Oracle下创建一个test的账户,然后 1.创建表:STOCK_PRICES --创建表格 CREATE TABLE STOCK_PRICES( RIC VARCHAR() PRIMARY KE ...

  4. oracle学习笔记1:windows下oracle数据库安装及.net调用oracle数据库

    1.下载32位或64位oracle数据库并且安装,安装时可以选择安装数据库实例或者不安装,如果不安装的话之后可以用Database Configuration Assistant(DBCA) 通过向导 ...

  5. ibatis.net调用oracle存储过返回游标SYS_REFCURSOR结果集

    最近在用ibatis.net框架和oracle 11g开发一套程序.其中有一个需求就是通过存储过程,查询指定条件的数据集. 但是在开发的过程中遇到了问题,问题如下: 1.如何通过ibatis.net执 ...

  6. Java调用Oracle存储Package

    Oracle的包Package中可以有很多存储,可通过该包的总调入口在java中直接调用. //java调用oracle的package代码 public boolean cal() throws j ...

  7. java基础---->java调用oracle存储过程(转)

    存储过程是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,存储在数据库中,经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它.今天 ...

  8. FSharp 调用 Oracle.ManagedDataAccess.dll

    FSharp 调用 Oracle.ManagedDataAccess.dll 1.Oracle.ManagedDataAccess.dll 的下载地址.好像如今必需要注冊才干下载. 即使是 64 位系 ...

  9. C#调用Oracle的存储过程时,连接字符串需要配置PLSQLRSet=1

    C#调用Oracle的存储过程时, 如果有个SYS_REFCURSOR的Output参数存储时, web.config文件中的连接字符串需要配置PLSQLRSet=1, 否则可能会报这个错:参数个数或 ...

随机推荐

  1. BoneCP 升级遇到的问题

    Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [c ...

  2. 自定义view(一)

    最近在学习自定义view  一遍看一别学顺便记录一下 1.View的测量-------->onMeasure() 首先,当我们要画一个图形的时候,必须知道三个数据:位置,长度,宽度   才能确定 ...

  3. Android开发学习之路-3DTouch效果模仿

    3D Touch是什么效果的大家应该都知道了.什么?不知道,那也没办法呀,我也没有iPhone 6s演示给你看的. 本篇博客要做的效果图: 来个低质量动图: 这个动图效果不是很好,实际上模糊效果应该是 ...

  4. Golang 生成随机数

    package main import ( "fmt" "math/rand" "time" ) func main() { rand.Se ...

  5. 从零开始编写自己的C#框架(14)——T4模板在逻辑层中的应用(三)

    原本关于T4模板原想分5个章节详细解说的,不过因为最近比较忙,也不想将整个系列时间拉得太长,所以就将它们整合在一块了,可能会有很多细节没有讲到,希望大家自己对着代码与模板去研究. 本章代码量会比较大, ...

  6. T-SQL:毕业生出门需知系列(九)

    <SQL 必知必会>读书笔记 -- 第9课 汇总数据 9.1 聚集函数:对某些行运行的函数,计算并返回一个值 案例: -- 确定表中函数 -- 获得表中某些行的和 -- 找出表列的最大值. ...

  7. ARM CPU大小端

    ARM CPU大小端: 大端模式:低位字节存在高地址上,高位字节存在低地址上 小端模式:高位字节存在高地址上,低位字节存在低地址上 STM32属于小端模式,简单的说,比如u32 temp=0X1234 ...

  8. Linux A机器免密码SSH登录B机器

    一.问题 如上,A机器经常需远程操作B机器,传输文件到B机器,每次输入帐号密码过于繁琐,下文通过ssh公钥能解免密码操作问题. 二.解决 1.方案 SSH认证采用公钥与私钥认证方式. 2.步骤 1) ...

  9. python 数据类型---列表使用 之二 (增删改查)

    列表的操作 1.列表的修改 >>> name ['Frank', 'Lee', 2, ['Andy', 'Troy']] >>> name[0] = "F ...

  10. 多线程并发同一个表问题(li)

    现有数据库开发过程中对事务的控制.事务锁.行锁.表锁的发现缺乏必要的方法和手段,通过以下手段可以丰富我们处理开发过程中处理锁问题的方法.For Update和For Update of使用户能够锁定指 ...