命名空间:Oracle.DataAccess.Client
组件:Oracle.DataAccess.dll(2.112.1.0)
ODP.NET 版本:ODP.NET for .NET Framework 2.0 或 ODP.NET for .NET Framework 4
工具:Microsoft Visual Studio Ultimate 2013 + Oracle SQL Developer 1.5.5 + Oracle Database 11g Enterprise Edition 11.2.0.1.0(32位) + TNS for 32-bit Windows 11.2.0.1.0
方式一:ArrayBind
当插入一条数据时,SQL 语句如下:
1 public void InsertDataRow(Dictionary<string, object> dataRow) 2 { 3 StringBuilder sbCmdText = new StringBuilder(); 4 sbCmdText.AppendFormat("INSERT INTO {0}(", m_TableName); 5 sbCmdText.Append(string.Join(",", dataRow.Keys.ToArray())); 6 sbCmdText.Append(") VALUES ("); 7 sbCmdText.Append(":" + string.Join(",:", dataRow.Keys.ToArray())); 8 sbCmdText.Append(")"); 9 10 using (OracleConnection conn = new OracleConnection()) 11 { 12 using (OracleCommand cmd = conn.CreateCommand()) 13 { 14 cmd.CommandType = CommandType.Text; 15 cmd.CommandText = sbCmdText.ToString(); 16 OracleParameter parameter = null; 17 OracleDbType dbType = OracleDbType.Object; 18 foreach (string colName in dataRow.Keys) 19 { 20 dbType = GetOracleDbType(dataRow[colName]); 21 parameter = new OracleParameter(colName, dbType); 22 parameter.Direction = ParameterDirection.Input; 23 parameter.OracleDbTypeEx = dbType; 24 parameter.Value = dataRow[colName]; 25 cmd.Parameters.Add(parameter); 26 } 27 conn.Open(); 28 int result = cmd.ExecuteNonQuery(); 29 } 30 } 31 }
此时,每一个 OracleParameter 的 Value 值都赋予单个字段的 一个具体值,这种也是最为传统的插入数据的方法。
Oracle V6 中 OCI 编程接口加入了数组接口特性。
当采用 ArrayBind 时,OraleParameter 的 Value 值则是赋予单个字段的 一个数组,即多条数据的该字段组合成的一个数组。此时 Oracle 仅需要执行一次 SQL 语句,即可在内存中批量解析并导入数据,减少程序与数据库之间来回的操作,其优点就是数据导入的总体时间明显减少,尤其是进程占用 CPU 的时间。
如果数据源是 DataTable 类型,首先把 DataTable 数据源,转换成 object[][] 类型,然后绑定 OracleParameter 的 Value 值为对应字段的一个 Object[] 数组即可;参考代码如下:
1 /// <summary> 2 /// 批量插入大数据量 3 /// </summary> 4 /// <param name="columnData">列名-列数据字典</param> 5 /// <param name="dataCount">数据量</param> 6 /// <returns>插入数据量</returns> 7 public int InsertBigData(Dictionary<string, object> columnData, int dataCount) 8 { 9 int result = 0; 10 if (columnData == null || columnData.Count < 1) 11 { 12 return result; 13 } 14 string[] colHeaders = columnData.Keys.ToArray(); 15 StringBuilder sbCmdText = new StringBuilder(); 16 if (columnData.Count > 0) 17 { 18 // 拼接INSERT的SQL语句 19 sbCmdText.AppendFormat("INSERT INTO {0}(", m_TableName); 20 sbCmdText.Append(string.Join(",", colHeaders)); 21 sbCmdText.Append(") VALUES ("); 22 sbCmdText.Append(m_ParameterPrefix + string.Join("," + m_ParameterPrefix, colHeaders)); 23 sbCmdText.Append(")"); 24 OracleConnection connection = null; 25 try 26 { 27 connection = new OracleConnection(GetConnectionString()); 28 using (OracleCommand command = connection.CreateCommand()) 29 { 30 command.ArrayBindCount = dataCount; 31 command.BindByName = true; 32 command.CommandType = CommandType.Text; 33 command.CommandText = sbCmdText.ToString(); 34 command.CommandTimeout = 1800; 35 OracleParameter parameter; 36 OracleDbType dbType = OracleDbType.Object; 37 foreach (string colName in colHeaders) 38 { 39 dbType = GetOracleDbType(columnData[colName]); 40 parameter = new OracleParameter(colName, dbType); 41 parameter.Direction = ParameterDirection.Input; 42 parameter.OracleDbTypeEx = dbType; 43 parameter.Value = columnData[colName]; 44 command.Parameters.Add(parameter); 45 } 46 connection.Open(); 47 OracleTransaction trans = connection.BeginTransaction(); 48 try 49 { 50 command.Transaction = trans; 51 result = command.ExecuteNonQuery(); 52 trans.Commit(); 53 } 54 catch (Exception ex) 55 { 56 trans.Rollback(); 57 throw ex; 58 } 59 } 60 } 61 finally 62 { 63 if (connection != null) 64 { 65 connection.Close(); 66 connection.Dispose(); 67 } 68 GC.Collect(); 69 GC.WaitForFullGCComplete(); 70 } 71 } 72 return result; 73 }
1 /// <summary> 2 /// 根据数据类型获取OracleDbType 3 /// </summary> 4 /// <param name="value">数据</param> 5 /// <returns>数据的Oracle类型</returns> 6 private static OracleDbType GetOracleDbType(object value) 7 { 8 OracleDbType dataType = OracleDbType.Object; 9 if (value is string[]) 10 { 11 dataType = OracleDbType.Varchar2; 12 } 13 else if (value is DateTime[]) 14 { 15 dataType = OracleDbType.TimeStamp; 16 } 17 else if (value is int[] || value is short[]) 18 { 19 dataType = OracleDbType.Int32; 20 } 21 else if (value is long[]) 22 { 23 dataType = OracleDbType.Int64; 24 } 25 else if (value is decimal[] || value is double[] || value is float[]) 26 { 27 dataType = OracleDbType.Decimal; 28 } 29 else if (value is Guid[]) 30 { 31 dataType = OracleDbType.Varchar2; 32 } 33 else if (value is bool[] || value is Boolean[]) 34 { 35 dataType = OracleDbType.Byte; 36 } 37 else if (value is byte[]) 38 { 39 dataType = OracleDbType.Blob; 40 } 41 else if (value is char[]) 42 { 43 dataType = OracleDbType.Char; 44 } 45 return dataType; 46 }