由于工作的原因,要使用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:app12product11.2.0client_1odp.netbin2.x
3.在项目中,添加引用,就可以使用了,用法跟自带的System.data.OracleClient差不多
5.批量插入:
1 //设置一个数据库的连接串
2 string connectStr = "User Id=scott;Password=tiger;Data Source=";
3 OracleConnection conn = new OracleConnection(connectStr);
4 OracleCommand command = new OracleCommand();
5 command.Connection = conn; //到此为止,还都是我们熟悉的代码,下面就要开始喽
6 //这个参数需要指定每次批插入的记录数
7 command.ArrayBindCount = recc;
8 //在这个命令行中,用到了参数,参数我们很熟悉,但是这个参数在传值的时候
9 //用到的是数组,而不是单个的值,这就是它独特的地方
10 command.CommandText = "insert into dept values(:deptno, :deptname, :loc)";
11 conn.Open();
12 //下面定义几个数组,分别表示三个字段,数组的长度由参数直接给出
13 int[] deptNo = new int[recc];
14 string[] dname = new string[recc];
15 string[] loc = new string[recc];
16 // 为了传递参数,不可避免的要使用参数,下面会连续定义三个
17 // 从名称可以直接看出每个参数的含义,不在每个解释了
18 OracleParameter deptNoParam = new OracleParameter("deptno",
19 OracleDbType.Int32);
20 deptNoParam.Direction = ParameterDirection.Input;
21 deptNoParam.Value = deptNo; command.Parameters.Add(deptNoParam);
22 OracleParameter deptNameParam = new OracleParameter("deptname",
23 OracleDbType.Varchar2);
24 deptNameParam.Direction = ParameterDirection.Input;
25 deptNameParam.Value = dname;
26 command.Parameters.Add(deptNameParam);
27 OracleParameter deptLocParam = new OracleParameter("loc", OracleDbType.Varchar2);
28 deptLocParam.Direction = ParameterDirection.Input;
29 deptLocParam.Value = loc;
30 command.Parameters.Add(deptLocParam);
31 Stopwatch sw = new Stopwatch();
32 sw.Start();
33 //在下面的循环中,先把数组定义好,而不是像上面那样直接生成SQL
34 for (int i = 0; i < recc; i++)
35 {
36 deptNo[i] = i;
37 dname[i] = i.ToString();
38 loc[i] = i.ToString();
39 }
40 //这个调用将把参数数组传进SQL,同时写入数据库
41 command.ExecuteNonQuery();
42 sw.Stop();
43 System.Diagnostics.Debug.WriteLine("批量插入:" + recc.ToString()
44 + "所占时间:" +sw.ElapsedMilliseconds.ToString());
6.上面的代码太乱,给一个已经封装好的批量插入的方法:
1 /**
2 * 批量插入数据
3 * @tableName 表名称
4 * @columnRowData 键-值存储的批量数据:键是列名称,值是对应的数据集合
5 * @conStr 连接字符串
6 * @len 每次批处理数据的大小
7 */
8 public static int BatchInsert(string tableName, Dictionary<string, object> columnRowData, string conStr, int len)
9 {
10 if (string.IsNullOrEmpty(tableName))
11 {
12 throw new ArgumentException("必须指定批量插入的表名称", "tableName");
13 }
14
15 if (columnRowData == null || columnRowData.Count < 1)
16 {
17 throw new ArgumentException("必须指定批量插入的字段名称", "columnRowData");
18 }
19
20 int iResult = 0;
21 string[] dbColumns = columnRowData.Keys.ToArray();
22 StringBuilder sbCmdText = new StringBuilder();
23 if (columnRowData.Count > 0)
24 {
25 //准备插入的SQL
26 sbCmdText.AppendFormat("INSERT INTO {0}(", tableName);
27 sbCmdText.Append(string.Join(",", dbColumns));
28 sbCmdText.Append(") VALUES (");
29 sbCmdText.Append(":" + string.Join(",:", dbColumns));
30 sbCmdText.Append(")");
31
32 using (OracleConnection conn = new OracleConnection(conStr))
33 {
34 using (OracleCommand cmd = conn.CreateCommand())
35 {
36 //绑定批处理的行数
37 cmd.ArrayBindCount = len;
38 cmd.BindByName = true;
39 cmd.CommandType = CommandType.Text;
40 cmd.CommandText = sbCmdText.ToString();
41 cmd.CommandTimeout = 600;//10分钟
42
43 //创建参数
44 OracleParameter oraParam;
45 List<IDbDataParameter> cacher = new List<IDbDataParameter>();
46 OracleDbType dbType = OracleDbType.Object;
47 foreach (string colName in dbColumns)
48 {
49 dbType = GetOracleDbType(columnRowData[colName]);
50 oraParam = new OracleParameter(colName, dbType);
51 oraParam.Direction = ParameterDirection.Input;
52 oraParam.OracleDbTypeEx = dbType;
53
54 oraParam.Value = columnRowData[colName];
55 cmd.Parameters.Add(oraParam);
56 }
57 //打开连接
58 conn.Open();
59
60 /*执行批处理*/
61 var trans = conn.BeginTransaction();
62 try
63 {
64 cmd.Transaction = trans;
65 iResult = cmd.ExecuteNonQuery();
66 trans.Commit();
67 }
68 catch (Exception ex)
69 {
70 trans.Rollback();
71 throw ex;
72 }
73 finally
74 {
75 if (conn != null) conn.Close();
76 }
77
78 }
79 }
80 }
81 return iResult;
82 }
83
84 /**
85 * 根据数据类型获取OracleDbType
86 */
87 private static OracleDbType GetOracleDbType(object value)
88 {
89 OracleDbType dataType = OracleDbType.Object;
90 if (value is string[])
91 {
92 dataType = OracleDbType.Varchar2;
93 }
94 else if (value is DateTime[])
95 {
96 dataType = OracleDbType.TimeStamp;
97 }
98 else if (value is int[] || value is short[])
99 {
100 dataType = OracleDbType.Int32;
101 }
102 else if (value is long[])
103 {
104 dataType = OracleDbType.Int64;
105 }
106 else if (value is decimal[] || value is double[] || value is float[])
107 {
108 dataType = OracleDbType.Decimal;
109 }
110 else if (value is Guid[])
111 {
112 dataType = OracleDbType.Varchar2;
113 }
114 else if (value is bool[] || value is Boolean[])
115 {
116 dataType = OracleDbType.Byte;
117 }
118 else if (value is byte[])
119 {
120 dataType = OracleDbType.Blob;
121 }
122 else if (value is char[])
123 {
124 dataType = OracleDbType.Char;
125 }
126 return dataType;
127 } 7.调用封装的方法:
8.完成。
对于服务器上的oracle版本问题,我们的是10g,但是我用的ODP是11g的,还是可以插入数据,没什么问题,貌似可以向下兼容