C#利用ODP.NET往oracle中高效插入百万数据
由于工作的原因,要使用winform来处理大量的数据,但是c#自带的System.data.OracleClient效率不是很高,在网上找了很久,找到了ODP.NET,是oracle为c#提供的。貌似从vs2010开始,微软开始推荐使用ODP.NET。效率的话,在没有索引的情况下,100万数据,不到10秒。刚开始使用的时候,由于不是很懂,所以有一些步骤是多余的,现在重新修改下。(这里是需要安装ODAC客户端)
1.从官网上下载ODAC,如果你是32位的机器,那下载32的;64位的,就下载64的。我的win7, 64位,所以我下载的是ODAC1120320_x64,具体地址:
64位:http://www.oracle.com/technetwork/database/windows/downloads/index-090165.html
32位:http://www.oracle.com/technetwork/developer-tools/visual-studio/downloads/index.html
2.解压,然后点击 setup.exe 安装,然后在这个地址:D:\app\12\product\11.2.0\client_1\odp.net\bin\2.x
3.在项目中,添加引用,就可以使用了,用法跟自带的System.data.OracleClient差不多
5.批量插入:
- //设置一个数据库的连接串
- string connectStr = "User Id=scott;Password=tiger;Data Source=";
- OracleConnection conn = new OracleConnection(connectStr);
- OracleCommand command = new OracleCommand();
- command.Connection = conn; //到此为止,还都是我们熟悉的代码,下面就要开始喽
- //这个参数需要指定每次批插入的记录数
- command.ArrayBindCount = recc;
- //在这个命令行中,用到了参数,参数我们很熟悉,但是这个参数在传值的时候
- //用到的是数组,而不是单个的值,这就是它独特的地方
- command.CommandText = "insert into dept values(:deptno, :deptname, :loc)";
- conn.Open();
- //下面定义几个数组,分别表示三个字段,数组的长度由参数直接给出
- int[] deptNo = new int[recc];
- string[] dname = new string[recc];
- string[] loc = new string[recc];
- // 为了传递参数,不可避免的要使用参数,下面会连续定义三个
- // 从名称可以直接看出每个参数的含义,不在每个解释了
- OracleParameter deptNoParam = new OracleParameter("deptno",
- OracleDbType.Int32);
- deptNoParam.Direction = ParameterDirection.Input;
- deptNoParam.Value = deptNo; command.Parameters.Add(deptNoParam);
- OracleParameter deptNameParam = new OracleParameter("deptname",
- OracleDbType.Varchar2);
- deptNameParam.Direction = ParameterDirection.Input;
- deptNameParam.Value = dname;
- command.Parameters.Add(deptNameParam);
- OracleParameter deptLocParam = new OracleParameter("loc", OracleDbType.Varchar2);
- deptLocParam.Direction = ParameterDirection.Input;
- deptLocParam.Value = loc;
- command.Parameters.Add(deptLocParam);
- Stopwatch sw = new Stopwatch();
- sw.Start();
- //在下面的循环中,先把数组定义好,而不是像上面那样直接生成SQL
- for (int i = ; i < recc; i++)
- {
- deptNo[i] = i;
- dname[i] = i.ToString();
- loc[i] = i.ToString();
- }
- //这个调用将把参数数组传进SQL,同时写入数据库
- command.ExecuteNonQuery();
- sw.Stop();
- System.Diagnostics.Debug.WriteLine("批量插入:" + recc.ToString()
- + "所占时间:" +sw.ElapsedMilliseconds.ToString());
6.上面的代码太乱,给一个已经封装好的批量插入的方法:
- /**
- * 批量插入数据
- * @tableName 表名称
- * @columnRowData 键-值存储的批量数据:键是列名称,值是对应的数据集合
- * @conStr 连接字符串
- * @len 每次批处理数据的大小
- */
- public static int BatchInsert(string tableName, Dictionary<string, object> columnRowData, string conStr, int len)
- {
- if (string.IsNullOrEmpty(tableName))
- {
- throw new ArgumentException("必须指定批量插入的表名称", "tableName");
- }
- if (columnRowData == null || columnRowData.Count < )
- {
- throw new ArgumentException("必须指定批量插入的字段名称", "columnRowData");
- }
- int iResult = ;
- string[] dbColumns = columnRowData.Keys.ToArray();
- StringBuilder sbCmdText = new StringBuilder();
- if (columnRowData.Count > )
- {
- //准备插入的SQL
- sbCmdText.AppendFormat("INSERT INTO {0}(", tableName);
- sbCmdText.Append(string.Join(",", dbColumns));
- sbCmdText.Append(") VALUES (");
- sbCmdText.Append(":" + string.Join(",:", dbColumns));
- sbCmdText.Append(")");
- using (OracleConnection conn = new OracleConnection(conStr))
- {
- using (OracleCommand cmd = conn.CreateCommand())
- {
- //绑定批处理的行数
- cmd.ArrayBindCount = len;
- cmd.BindByName = true;
- cmd.CommandType = CommandType.Text;
- cmd.CommandText = sbCmdText.ToString();
- cmd.CommandTimeout = ;//10分钟
- //创建参数
- OracleParameter oraParam;
- List<IDbDataParameter> cacher = new List<IDbDataParameter>();
- OracleDbType dbType = OracleDbType.Object;
- foreach (string colName in dbColumns)
- {
- dbType = GetOracleDbType(columnRowData[colName]);
- oraParam = new OracleParameter(colName, dbType);
- oraParam.Direction = ParameterDirection.Input;
- oraParam.OracleDbTypeEx = dbType;
- oraParam.Value = columnRowData[colName];
- cmd.Parameters.Add(oraParam);
- }
- //打开连接
- conn.Open();
- /*执行批处理*/
- var trans = conn.BeginTransaction();
- try
- {
- cmd.Transaction = trans;
- iResult = cmd.ExecuteNonQuery();
- trans.Commit();
- }
- catch (Exception ex)
- {
- trans.Rollback();
- throw ex;
- }
- finally
- {
- if (conn != null) conn.Close();
- }
- }
- }
- }
- return iResult;
- }
- /**
- * 根据数据类型获取OracleDbType
- */
- private static OracleDbType GetOracleDbType(object value)
- {
- OracleDbType dataType = OracleDbType.Object;
- if (value is string[])
- {
- dataType = OracleDbType.Varchar2;
- }
- else if (value is DateTime[])
- {
- dataType = OracleDbType.TimeStamp;
- }
- else if (value is int[] || value is short[])
- {
- dataType = OracleDbType.Int32;
- }
- else if (value is long[])
- {
- dataType = OracleDbType.Int64;
- }
- else if (value is decimal[] || value is double[] || value is float[])
- {
- dataType = OracleDbType.Decimal;
- }
- else if (value is Guid[])
- {
- dataType = OracleDbType.Varchar2;
- }
- else if (value is bool[] || value is Boolean[])
- {
- dataType = OracleDbType.Byte;
- }
- else if (value is byte[])
- {
- dataType = OracleDbType.Blob;
- }
- else if (value is char[])
- {
- dataType = OracleDbType.Char;
- }
- return dataType;
- }
7.调用封装的方法:
8.完成。
对于服务器上的oracle版本问题,我们的是10g,但是我用的ODP是11g的,还是可以插入数据,没什么问题,貌似可以向下兼容
C#利用ODP.NET往oracle中高效插入百万数据的更多相关文章
- 获得Oracle中刚插入的数据的ID(for produce)
在sql sever中实现插入数据的自动增长是很容易的,但是在oracle数据库中实现这一操作不是很容易,同时要想在.net中实现获取新插入数据的id,而 且不会出现读错的情况,就更显得困难了,为了解 ...
- Oracle:高效插入大量数据经验之谈
来源于:http://www.cnblogs.com/liwenzhen238/p/3610518.html 在很多时候,我们会需要对一个表进行插入大量的数据,并且希望在尽可能短的时间内完成该工作,这 ...
- Oracle中批量插入
为了防止OracleConnection的重复打开和关闭,使用begin end:将sql语句包在里面,然后一次性执行提高插入的效率. 下面代码中要插入的数据在list集合中,如果list集合的cou ...
- Oracle中使用游标转换数据表中指定字段内容格式(拼音转数字)
应用场景:将数据表TB_USER中字段NNDP的内容中为[sannanyinv]转换为[3男1女] 主要脚本:一个游标脚本+分割字符串函数+拼音转数字脚本 操作步骤如下: 1.创建类型 create ...
- C# 利用mysql.data 在mysql中创建数据库及数据表
C# 利用mysql.data 在mysql中创建数据库及数据表 using System; using System.Collections.Generic; using System.Linq; ...
- Oracle中如何插入特殊字符: &amp; 和 &#39; (多种解决方案)
Oracle中如何插入特殊字符:& 和 ' (多种解决方案)今天在导入一批数据到Oracle时,碰到了一个问题:Toad提示要给一个自定义变量AMP赋值,一开始我很纳闷,数据是一系列的Inse ...
- win8下在microsoft visual studio 2012利用ODP.NET连接ORACLE 12c
老板要求我搭个ASP.NET框架,并且连接上ORACLE数据库,听起来好像挺简单的,但就是连第一步连接ORACLE我都搞了两天╮(╯▽╰)╭ 首先,项目书上要求用ORACLE 10G,可我自己的本本装 ...
- 在oracle中存入date类型数据遇到的问题及其解决方法(利用java.sql.date和Timestamp)
转自:https://blog.csdn.net/ShadowerWArden/article/details/80652377 1. 使用JDBC操作Oracle数据库时,使用java.sql.Da ...
- oracle中的rowid和数据行的结构
在oracle数据库系统中每一行都有一个rowid,oracle数据库系统就是利用rowid来定位数据行的.rowid也是oracle中内置的一个标量数据类型 rowid有一下特点; 是数据库中每一行 ...
随机推荐
- MFC 堆栈溢出 test dword ptr [eax],eax ; probe page.
今天调试程序的时候,发现一个奇怪的问题,之前调试都没问题的,今早加了一点东西,就出现错误,跳到调试位置,如下4行红色部分 ; Find next lower page and probe cs20: ...
- display 与 visibility
项目开发中经常会遇到需要显示和隐藏DOM元素.常用的两个是display,visibility属性,高级点的会用到angularJS的ng-show,ng-if指令. W3标准对这个两个属性的解释如下 ...
- oracle sql语句中使用if逻辑
l在 SQL 语句中使用IF-THEN-ELSE 逻辑 l l使用两种方法: •CASE 表达式:SQL99的语法,类似Basic,比较繁琐 •DECODE 函数:Oracle自己的语法,类似Java ...
- [转]C++强制类型转换
dynamic_cast: 通常在基类和派生类之间转换时使用,run-time castconst_cast: 主要针对const和volatile的转换. static_cast: ...
- [转]javascript函数定义表达式和函数声明的区别
在javascript中,函数有两种定义写法,函数定义表达式和函数声明,其例子分别如下所示: var test = function(x){ return x; } function test(x){ ...
- sql查询每门课程成绩最高的学生
给出数据库(sco)如下图: 查出每门课程成绩最高的学生 select b.id,b.kemu,b.name,b.chengji from (select kemu,max(chengji) maxc ...
- display:inline,display:inline-block,display:block 区别
之前一直迷惑于display:inline/inline-block/block的异同,在度娘谷哥的帮助下,突然有了一点思路. 按照网上的介绍,inline将对象转化为内联元素,block将对象转化为 ...
- trident教程
(一)理论基础更多理论以后再补充,或者参考书籍1.trident是什么?Trident is a high-level abstraction for doing realtime computi ...
- 深入mysql慢查询设置的详解
set long_query_time=1; #设置慢查询时间为1 秒; set global slow_query_log=on; #开启慢查询日志; show global status like ...
- php 编译安装选项
./configure --prefix=/usr/local/php/ --with-config-file-path=/etc/php5/cli/ --with-config-file-scan- ...