前言
前段時間一直在忙著項目上線,在做項目的同時遇到了一些之前不曾碰到的問題,因為沒有經驗,只能從網上找一些相關的解決方案,但是網上提供的資料實在是太雜,有的根本不能用,耗時又耗力。
我希望把我這段時間遇到的問題記錄下來,去幫助那些當時和我一樣“饑渴”的人,以減少時間成本,大家放心,遇到的這些問題提供的解決方案都是經過我們測試,現在正在用的,基本上沒什么問題。有什么問題,大家也可以進行探討,因為問題很多,有些記不起來了,我只能寫些可以記起來的分享給大家。
插一句,就是大家在搜問題的時候,盡量用關鍵字,不是你搜不到問題的答案,而是你搜問題的方式有問題,而且盡量用google,大家用過就知道為什么了,看不懂的有google翻譯。
批量插入
我們在.net操作大數據的時候,有時候會遇到大量數據插入的情況,遇到這種方式,我們遇到最笨的方式是forearch插入,很少的數據是可以,但是幾千條,幾萬條就死掉了,這種方式性能很差。既然如此,微軟不可能沒有好的解決方案的,這就是DataAdapter,我貼下批量插入的:
public static bool MultiInsertData(DataSet ds, string Columns, string tableName) { using (OracleConnection connection = new OracleConnection(connectionString)) { string SQLString = string.Format("select {0} from {1} where rownum=0", Columns, tableName); using (OracleCommand cmd = new OracleCommand(SQLString, connection)) { try { connection.Open(); OracleDataAdapter myDataAdapter = new OracleDataAdapter(); myDataAdapter.SelectCommand = new OracleCommand(SQLString, connection); myDataAdapter.UpdateBatchSize = 0; OracleCommandBuilder custCB = new OracleCommandBuilder(myDataAdapter); DataTable dt = ds.Tables[0].Copy(); DataTable dtTemp = dt.Clone(); int times = 0; for (int count = 0; count < dt.Rows.Count; times++) { for (int i = 0; i < 400 && 400 * times + i < dt.Rows.Count; i++, count++) { dtTemp.Rows.Add(dt.Rows[count].ItemArray); } myDataAdapter.Update(dtTemp); dtTemp.Rows.Clear(); } dt.Dispose(); dtTemp.Dispose(); myDataAdapter.Dispose(); return true; } catch (System.Data.OracleClient.OracleException E) { connection.Close(); return false; } } } }
大家都是搞編程的,一看就明白,我就簡單的說下,參數ds是要更新的數據集,Columns是要插入的列表,TableName是要插入的表名,這里需要強調的一點是,插入數據集里的表的字段和類型必須和數據庫那邊一致,這點重要,要不然插入會報錯。
這里還有加了個分段插入,就是那個for,每400條插入一次,這樣可以避免插入的數據太大,會發生超時異常。
我做項目的時候遇到這種情況是:有些數據是要先保存到本地,比如SqlLite,然后再上傳到數據庫。
這里給大家個建議,如果用到wcf,就在傳輸前對數據集進行壓縮,然后到服務端再解壓下,這樣傳輸速度會很快。有時間給大家提供壓縮的方法。
批量更新
批量更新和批量插入差不多的邏輯,我先貼下代碼:
public static bool MultiUpdateData(DataTable data, string Columns, string tableName) { using (OracleConnection connection = new OracleConnection(connectionString)) { string SQLString = string.Format("select {0} from {1} where rownum=0", Columns, tableName); using (OracleCommand cmd = new OracleCommand(SQLString, connection)) { try { connection.Open(); OracleDataAdapter myDataAdapter = new OracleDataAdapter(); myDataAdapter.SelectCommand = new OracleCommand(SQLString, connection); OracleCommandBuilder custCB = new OracleCommandBuilder(myDataAdapter); custCB.ConflictOption = ConflictOption.OverwriteChanges; custCB.SetAllValues = true; foreach (DataRow dr in data.Rows) { if (dr.RowState == DataRowState.Unchanged) dr.SetModified(); } myDataAdapter.Update(data); data.AcceptChanges(); myDataAdapter.Dispose(); return true; } catch (System.Data.OracleClient.OracleException E) { connection.Close(); return false; } } } }
大家看代碼發現和上面插入是差不多的,但是有幾點注意的地方我說下,數據集行的狀態RowState必須是Modified狀態,不是的話需要設置一下,還有就是更新的數據集中必須包含主鍵,沒有的話就會報錯。
重要的一點就是data.AcceptChanges();這句代碼,如果注釋掉的話,雖然myDataAdapter.Update(data);這段代碼更新了,但是數據庫那邊還是不行的,我的理解是這樣:Adapter本身是適配器的意思,適配器是連接兩個物體之間的橋梁,就像協議一樣,兩邊都通過才可以完成整個過程。data.AcceptChanges();的意思是應用數據集的更改,我測試過在數據集傳輸之前應用更新,也是可以更新到數據庫的,可能就是dr.SetModified();這段代碼在控制吧,如果數據庫中的數據在數據集中發生變化,就會生成相應的Uodate,執行更新,這些都是我的猜測,底層的東西我不是很了解,這也是我欠缺的地方,等項目上線完一定要惡補下。
批量更新我應用的場景是:datagridview綁定查詢的數據,對數據進行修改,然后批量更新到數據庫。
希望可以幫到需要幫助的朋友。。。
文章列表