.Net2.0提供了SqlBulkCopy 类。使用 SqlBulkCopy 类向 SQL Server 表写入数据,数据源不限于 SQL Server,可以使用任何数据源,只要数据可加载到DataTable实例或可使用IDataReader实例读取数据。Oracle 11g同样提供了类似的做法。在Oracle.DataAccess.dll(2.112.1.0)中,oracle提供了OralceBulkCopy类,实现了向Oracle表写入数据。
但是现阶段,很多项目还在使用Oracle 10g。在Oracle 10g下并不能使用这一新特性。(本人已经试过加载Oralce11g中的Oracle.DataAccess.dll,但在没安装Oracle 11g客户端的情况下,仍然无法正常使用)本人就试着简单写了一个简单的类似于SqlBulkCopy的类,以便大家使用。
View Code
1 using System;
2 using System.Collections.Generic;
3 using System.Data;
4 using System.Text;
5 using System.IO;
6 using System.Diagnostics;
7 using Oracle.DataAccess.Client;
8
9 namespace SK.Common
10 {
11 /// <summary>
12 /// Function:使您可以用其他源的数据有效批量加载 Oracle 表
13 /// Author :shike
14 /// CreationDate:2011-01-17
15 /// </summary>
16 public class OracleBulkCopy : IDisposable
17 {
18 #region Variables and Properties
19 /// <summary>
20 /// 在每次处理完 BatchSize 属性指定的行数时发生
21 /// </summary>
22 public event OracleRowsCopiedEventHandler OracleRowsCopied;
23
24 /// <summary>
25 /// 数据源DataTable与数据库 字段的映射集合,key:目标表字段名(英文名),value:源表字段名(中文名)
26 /// </summary>
27 private Dictionary<string, string> _columnMappings;
28 /// <summary>
29 /// 数据源DataTable与数据库 字段的映射集合,key:目标表字段名(英文名),value:源表字段名(中文名)
30 /// </summary>
31 public Dictionary<string, string> ColumnMappings
32 {
33 get { return _columnMappings; }
34 set { _columnMappings = value; }
35 }
36
37 /// <summary>
38 /// 每一批次中的行数。在每一批次结束时,将该批次中的行发送到服务
39 /// </summary>
40 private int _batchSize;
41 /// <summary>
42 /// 每一批次中的行数。在每一批次结束时,将该批次中的行发送到服务
43 /// </summary>
44 public int BatchSize
45 {
46 get { return _batchSize; }
47 set { _batchSize = value; }
48 }
49
50 /// <summary>
51 /// 服务器上目标表的名称
52 /// </summary>
53 private string _destinationTableName;
54 /// <summary>
55 /// 服务器上目标表的名称
56 /// </summary>
57 public string DestinationTableName
58 {
59 get { return _destinationTableName; }
60 set { _destinationTableName = value; }
61 }
62
63 /// <summary>
64 /// 数据库连接字符串
65 /// </summary>
66 private string _connectionString;
67
68 /// <summary>
69 /// 数据库连接
70 /// </summary>
71 private OracleConnection _oracleConn;
72
73 /// <summary>
74 /// 数据库执行的SQL语句或存储过程
75 /// </summary>
76 private OracleCommand _oracleCommand;
77 #endregion
78
79 /// <summary>
80 /// 基于提供的 connectionString 初始化 OracleBulkCopy 类的新实例
81 /// </summary>
82 /// <param name="connectionString">数据库连接字符串</param>
83 public OracleBulkCopy(string connectionString)
84 {
85 this._batchSize = 0;
86 this._destinationTableName = string.Empty;
87 this._connectionString = connectionString;
88
89 this._oracleConn = new OracleConnection(this._connectionString);
90 this._oracleCommand = new OracleCommand();
91 this._oracleCommand.Connection = this._oracleConn;
92 }
93
94 /// <summary>
95 /// 将所提供的 System.Data.DataTable 中的所有行复制到 DestinationTableName 属性指定的目标表中
96 /// </summary>
97 /// <param name="dt">提供的 System.Data.DataTable</param>
98 public void WriteToServer(DataTable dt)
99 {
100 try
101 {
102 //打开连接
103 this.open();
104 //计算出一共需要提交的批次的数量
105 int mCount = (int)(dt.Rows.Count / this._batchSize) + 1;
106
107 //循环分批次提交
108 for (int i = 0; i < mCount; i++)
109 {
110 //清空参数集合
111 this._oracleCommand.Parameters.Clear();
112 StringBuilder fStr = new StringBuilder();//字段
113 StringBuilder pStr = new StringBuilder();//参数
114 if (i != mCount - 1)//非最后一批
115 {
116 this._oracleCommand.ArrayBindCount = this._batchSize;
117
118 foreach (KeyValuePair<string, string> kv in this._columnMappings)
119 {
120 //拼字段
121 fStr.Append(kv.Key);
122 fStr.Append(',');
123 pStr.Append(":" + kv.Key);
124 pStr.Append(',');
125
126 //生成参数,参数是数字组的形式
127 OracleParameter param = new OracleParameter(kv.Key, OracleDbType.NVarchar2);
128 param.Direction = ParameterDirection.Input;
129 string[] paramValue = new string[this._batchSize];
130 for (int j = i * this._batchSize; j < (i + 1) * this._batchSize; j++)
131 {
132 string v = dt.Rows[j][kv.Value].ToString();
133 paramValue[j % this._batchSize] = v;
134 }
135
136 param.Value = paramValue;
137 this._oracleCommand.Parameters.Add(param);
138 }
139 this._oracleCommand.CommandText =
140 string.Format("insert into {0}({1}) values({2})",
141 this._destinationTableName,
142 fStr.ToString().TrimEnd(','),
143 pStr.ToString().TrimEnd(','));
144 this._oracleCommand.ExecuteNonQuery();
145
146 OracleRowsCopiedEventArgs arg1 = new OracleRowsCopiedEventArgs(true, false);
147 this.OracleRowsCopied(this, arg1);
148 }//最后一批
149 else
150 {
151 this._oracleCommand.ArrayBindCount = dt.Rows.Count - (i * this._batchSize);
152
153 foreach (KeyValuePair<string, string> kv in this._columnMappings)
154 {
155 //拼字段
156 fStr.Append(kv.Key);
157 fStr.Append(',');
158 pStr.Append(":" + kv.Key);
159 pStr.Append(',');
160
161 //生成参数,参数是数字组的形式
162 OracleParameter param = new OracleParameter(kv.Key, OracleDbType.NVarchar2);
163 param.Direction = ParameterDirection.Input;
164 string[] paramValue = new string[dt.Rows.Count - (i * this._batchSize)];
165 for (int j = i * this._batchSize; j < dt.Rows.Count; j++)
166 {
167 string v = dt.Rows[j][kv.Value].ToString();
168 paramValue[j % this._batchSize] = v;
169 }
170
171 param.Value = paramValue;
172 this._oracleCommand.Parameters.Add(param);
173 }
174 this._oracleCommand.CommandText =
175 string.Format("insert into {0}({1}) values({2})",
176 this._destinationTableName,
177 fStr.ToString().TrimEnd(','),
178 pStr.ToString().TrimEnd(','));
179 this._oracleCommand.ExecuteNonQuery();
180
181 OracleRowsCopiedEventArgs arg3 = new OracleRowsCopiedEventArgs(true, true);
182 this.OracleRowsCopied(this, arg3);
183 }
184 }
185 }
186 catch (Exception ex)
187 {
188 OracleRowsCopiedEventArgs arg2 = new OracleRowsCopiedEventArgs(false, false);
189 this.OracleRowsCopied(this, arg2);
190 SystemLog.Error("导入数据失败!", e);
191 }
192 finally
193 {
194 this.close();
195 }
196 }
197
198 #region IDisposable 成员
199
200 public void Dispose()
201 {
202 if (this._oracleCommand != null)
203 this._oracleCommand.Dispose();
204 if (this._oracleConn != null)
205 this._oracleConn.Dispose();
206 }
207
208 #endregion
209
210 #region privateMethod
211 /// <summary>
212 /// 打开数据库连接
213 /// </summary>
214 private void open()
215 {
216 if (this._oracleConn.State == ConnectionState.Closed)
217 {
218 try
219 {
220 this._oracleConn.Open();
221 }
222 catch (Exception e)
223 {
224 SystemLog.Error("数据库连接失败!", e);
225 }
226 }
227 }
228
229 /// <summary>
230 /// 关闭数据库连接
231 /// </summary>
232 private void close()
233 {
234 try
235 {
236 if (this._oracleConn.State == ConnectionState.Open)
237 {
238 this._oracleConn.Close();
239 }
240 }
241 catch (Exception ex)
242 {
243 SystemLog.Error("关闭数据库连接失败!", ex);
244 }
245 }
246 #endregion
247 }
248
249 /// <summary>
250 /// Function:OracleBulkCopy 的 OracleBulkCopy.OracleRowsCopied事件的方法
251 /// Author :shike
252 /// CreationDate:2011-01-17
253 /// </summary>
254 /// <param name="sender">事件源</param>
255 /// <param name="e"></param>
256 public delegate void OracleRowsCopiedEventHandler(object sender, OracleRowsCopiedEventArgs e);
257
258 /// <summary>
259 /// Function:表示传递给OracleRowsCopiedEventHandler 的参数集
260 /// Author :shike
261 /// CreationDate:2011-01-17
262 /// </summary>
263 public class OracleRowsCopiedEventArgs : EventArgs
264 {
265 /// <summary>
266 /// 是否全部提交成功
267 /// </summary>
268 public bool IsAllSucceed { get; set; }
269 /// <summary>
270 /// 是否单批提交成功
271 /// </summary>
272 public bool IsSucceed { get; set; }
273
274 public OracleRowsCopiedEventArgs()
275 : this(false, false)
276 { }
277
278 public OracleRowsCopiedEventArgs(bool isSucceed, bool isAllSucceed)
279 {
280 this.IsSucceed = isSucceed;
281 this.IsAllSucceed = isAllSucceed;
282 }
283 }
284 }