天天看點

IBatis.Net 下使用SqlBulkCopy 大批量導入資料 問題解決

SQLBulkCopy是繼承SQLClient空間下的一個特殊類,它可以幫助我們以映射的方式把DataTable和DataReader資料大批量導入到資料庫對應表中

public void Inert2DBBySqlBulkCopy(DataTable data, string tableName)
{
BaseDao basdd = new BaseDao();
using (SqlConnection conn = new SqlConnection(basdd.SqlNormMap.DataSource.ConnectionString))
{
if (conn.State != ConnectionState.Open)
conn.Open();
using (SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(conn))
{
sqlBulkCopy.ColumnMappings.Add(0, "CarModelID");
sqlBulkCopy.ColumnMappings.Add(1, "TranConfID");
sqlBulkCopy.ColumnMappings.Add(2, "TranValue");
sqlBulkCopy.ColumnMappings.Add(3, "CreatorID");
sqlBulkCopy.ColumnMappings.Add(4, "Creator");
sqlBulkCopy.ColumnMappings.Add(5, "OptDataType");
sqlBulkCopy.BatchSize = data.Rows.Count;
sqlBulkCopy.BulkCopyTimeout = 30;
sqlBulkCopy.DestinationTableName = tableName;
sqlBulkCopy.WriteToServer(data);
}
if (conn.State != ConnectionState.Closed)
conn.Close();
}
}
           

其中要注意都是:

Table表中的字段名稱,字段順序,字段類型 必須和插入的sqlBulkCopy.ColumnMappings.Add的插入順序是一模一樣的,如下圖,自定義一個Class

public class JJJModel
   {
       public int? CarModelID { get; set; }
       public int TranConfID { get; set; }
       public string TranValue { get; set; }
       public int CreatorID { get; set; }
       public string Creator { get; set; }
       public int OptDataType { get; set; }
   }
           

插入的時候的代碼

//比對款式Id和配置ID  拼成二維表資料
                            for (int i = 0; i < listCarModelID.Count(); i++)
                            {
                                msindex = i;
                                for (int j = 0; j < listTranF.Count(); j++)
                                {
                                    JJJModel jj = new JJJModel();
                                    jj.CarModelID = Convert.ToInt32(listCarModelID[i]);        //款型ID
                                    jj.TranConfID = Convert.ToInt32(listTranF[j].ToString());   //配置ID
                                    jj.TranValue = dtCMTranConf.Rows[i][j + 2].ToString().ToUpper();//值
                                    jj.CreatorID = UserId;
                                    jj.Creator = UserName;
                                    jj.OptDataType = CarConst.OptDataType20;
                                    listTranExcel.Add(jj);
                                }
                            }
           

異常資訊:樓主剛開始寫的時候也是按照上邊開發,百萬資料資料也是輕輕松松分分鐘搞定的。可是後來,産品有提到一個要求,就是要大批量更新資料,而且也是速度很快的時間内完成。

解決SQLBulkCopy批量更新問題:

于是就想先删除 那些要插入的資料,再批量插入要更新的資料,于是乎就捋起胳膊大幹一場,當然删除和批量插入肯定是同一張表(Table_A),也肯定是在同一個事務中,後來,後來竟然插入不成功,

就一直在sqlBulkCopy.WriteToServer(data);這句代碼裡邊一直轉悠,一直到sql連接配接逾時結束調試程式。我就郁了個悶的,同樣的代碼怎麼會出現這個問題。

後來仔細檢視對比一下,原來問題是由于對同一個表(Table_A) 先删除,再批量插入的時候  都是在同一個事務中 ,因為删除的時候 就把表給lock了,當然隻能插入失敗了.

那怎麼辦呢,于是樓主就扔然 還讓先删除,再插入 在同一個事務中,隻是在資料做了個操作,建立一個同樣和目标表(Table_A)一樣的臨時表(Table_Temp),在執行事務開始時候,

先把要插入的資料插入到臨時表Table_Temp,然後執行存儲過程,再存儲過程中 删除目标表(Table_A)中的存在于臨時表(Table_Temp)裡邊的ID條件資料.

然後再用Insert Into  目标表(Table_A) select  from 臨時表(Table_Temp) 的方法把臨時表的資料插入到目标表(Table_A)中.這樣就妥妥的完成了。

PS:存儲過程中寫個事務,完成不完成都要把臨時表(Table_Temp)的資料清空哦 ,這個可不能忘記了