天天看點

.Net中DataAdapter批量插入和更新資料總結

前言

  前段時間一直在忙着項目上線,在做項目的同時遇到了一些之前不曾碰到的問題,因為沒有經驗,隻能從網上找一些相關的解決方案,但是網上提供的資料實在是太雜,有的根本不能用,耗時又耗力。

  我希望把我這段時間遇到的問題記錄下來,去幫助那些當時和我一樣“饑渴”的人,以減少時間成本,大家放心,遇到的這些問題提供的解決方案都是經過我們測試,現在正在用的,基本上沒什麼問題。有什麼問題,大家也可以進行探讨,因為問題很多,有些記不起來了,我隻能寫些可以記起來的分享給大家。

  插一句,就是大家在搜問題的時候,盡量用關鍵字,不是你搜不到問題的答案,而是你搜問題的方式有問題,而且盡量用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綁定查詢的資料,對資料進行修改,然後批量更新到資料庫。

  希望可以幫到需要幫助的朋友。。。

作者:田園裡的蟋蟀

微信公衆号:你好架構

出處:http://www.cnblogs.com/xishuai/

公衆号會不定時的分享有關架構的方方面面,包含并不局限于:Microservices(微服務)、Service Mesh(服務網格)、DDD/TDD、Spring Cloud、Dubbo、Service Fabric、Linkerd、Envoy、Istio、Conduit、Kubernetes、Docker、MacOS/Linux、Java、.NET Core/ASP.NET Core、Redis、RabbitMQ、MongoDB、GitLab、CI/CD(持續內建/持續部署)、DevOps等等。

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接。

分享到:

QQ空間

新浪微網誌

騰訊微網誌

微信

更多