由于工作的原因,要使用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中高效插入百万数据的更多相关文章

  1. 获得Oracle中刚插入的数据的ID(for produce)

    在sql sever中实现插入数据的自动增长是很容易的,但是在oracle数据库中实现这一操作不是很容易,同时要想在.net中实现获取新插入数据的id,而 且不会出现读错的情况,就更显得困难了,为了解 ...

  2. Oracle:高效插入大量数据经验之谈

    来源于:http://www.cnblogs.com/liwenzhen238/p/3610518.html 在很多时候,我们会需要对一个表进行插入大量的数据,并且希望在尽可能短的时间内完成该工作,这 ...

  3. Oracle中批量插入

    为了防止OracleConnection的重复打开和关闭,使用begin end:将sql语句包在里面,然后一次性执行提高插入的效率. 下面代码中要插入的数据在list集合中,如果list集合的cou ...

  4. Oracle中使用游标转换数据表中指定字段内容格式(拼音转数字)

    应用场景:将数据表TB_USER中字段NNDP的内容中为[sannanyinv]转换为[3男1女] 主要脚本:一个游标脚本+分割字符串函数+拼音转数字脚本 操作步骤如下: 1.创建类型 create ...

  5. C# 利用mysql.data 在mysql中创建数据库及数据表

    C# 利用mysql.data 在mysql中创建数据库及数据表 using System; using System.Collections.Generic; using System.Linq; ...

  6. Oracle中如何插入特殊字符: &amp;amp; 和 &amp;#39; (多种解决方案)

    Oracle中如何插入特殊字符:& 和 ' (多种解决方案)今天在导入一批数据到Oracle时,碰到了一个问题:Toad提示要给一个自定义变量AMP赋值,一开始我很纳闷,数据是一系列的Inse ...

  7. win8下在microsoft visual studio 2012利用ODP.NET连接ORACLE 12c

    老板要求我搭个ASP.NET框架,并且连接上ORACLE数据库,听起来好像挺简单的,但就是连第一步连接ORACLE我都搞了两天╮(╯▽╰)╭ 首先,项目书上要求用ORACLE 10G,可我自己的本本装 ...

  8. 在oracle中存入date类型数据遇到的问题及其解决方法(利用java.sql.date和Timestamp)

    转自:https://blog.csdn.net/ShadowerWArden/article/details/80652377 1. 使用JDBC操作Oracle数据库时,使用java.sql.Da ...

  9. oracle中的rowid和数据行的结构

    在oracle数据库系统中每一行都有一个rowid,oracle数据库系统就是利用rowid来定位数据行的.rowid也是oracle中内置的一个标量数据类型 rowid有一下特点; 是数据库中每一行 ...

随机推荐

  1. iOS9中请求出现App Transport Security has blocked a cleartext HTTP (http://)

    错误描述: App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecu ...

  2. HTML入门学习

    html 基本结构    <!DOCTYPE html> ----------------声明文档的解析类型, 避免浏览器的怪异模式<html> --------------- ...

  3. 自定义异常throw

    简单自定义一个年龄小于等于0,或者大于120会出现的异常 首先继承父类Exception,调用父类的构造器,这样才可以报出自己想要的异常 public class AgeException exten ...

  4. 无效的过程调用或参数: 'Instr'解决方法

    以前我一直使用ASP无组件上传类来上传文件.但是今天又个客户反映说.不能上传.出现错误.,但在我电脑上测试没问题.后来发现客户用的是IE8 于是开始找解决方法 错误如下:Microsoft VBScr ...

  5. 数据库 数据库SQL语句五

    集合运算 union 并集(两个集合如果有重复部分,那么只显示一次重复部分) union all 并集(两个集合如果有重复部分,那么重复部分显示两次) intersect 交集 minus 差集 -- ...

  6. 一句话输出NGINX日志访问IP前十位排行

    AWK的数组字段自增加,然后取值的方法,要记得哟. 还有,SORT指定列排行,也常用的.

  7. Intel hex 文件格式解密

    Intel hex 文件常用来保存单片机或其他处理器的目标程序代码.它保存物理程序存储区中的目标代码映象.一般的编程器都支持这种格式. Intel hex 文件全部由可打印的ASCII字符组成(可以用 ...

  8. 2个Web上传组件

    http://www.uploadify.com/download/ http://gmupload.tanjun.com.cn/

  9. Qt编程之QString 处理换行

    由于之间写过的一篇文章,Unix,windows,Mac里面的换行符不一样,导致处理也不一样,我现在要用QString以行分割(读取的文本文件的里面有换行符).所以要通吃这三种换行符 http://w ...

  10. Linux系统编程(37)—— socket编程之原始套接字

    原始套接字的特点 原始套接字(SOCK_RAW)可以用来自行组装IP数据包,然后将数据包发送到其他终端.也就是说原始套接字是基于IP数据包的编程(SOCK_PACKET是基于数据链路层的编程).另外, ...