由於工作的原因,要使用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.批量插入:
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的,還是可以插入數據,沒什么問題,貌似可以向下兼容