C#使用SqlDataAdapter 實現資料的批量插入和更新
近日由於專案要求在需要實現中型資料的批量插入和更新,晚上無聊,在網上看到看到這樣的一個實現方法,特摘抄過來,以便以後可能用到參考。
一.資料的插入
DateTime begin = DateTime.Now; string connectionString = ......; using(SqlConnection conn = new SqlConnection(connectionString)){ conn.Open(); SqlDataAdapter sd = new SqlDataAdapter(); sd.SelectCommand = newSqlCommand("select devid,data_time,data_value from CurrentTest", conn); sd.InsertCommand = new SqlCommand("insert into CurrentTest (devid,data_time,data_value) " + " values (@devid,@data_time,@data_value);", conn); sd.InsertCommand.Parameters.Add("@devid", SqlDbType.Char, 18, "devid"); sd.InsertCommand.Parameters.Add("@data_time", SqlDbType.Char, 19, "data_time"); sd.InsertCommand.Parameters.Add("@data_value", SqlDbType.Int, 8, "data_value"); sd.InsertCommand.UpdatedRowSource = UpdateRowSource.None; sd.UpdateBatchSize = 0; DataSet dataset = newDataSet(); sd.Fill(dataset); Random r = new Random(1000); for (int i = 0; i < 100000; i++) { object[] row = {"DEVID"+i,DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),r.Next(1,1000) }; dataset.Tables[0].Rows.Add(row); if (i % 300 == 0) { sd.Update(dataset.Tables[0]); dataset.Tables[0].Clear(); } } sd.Update(dataset.Tables[0]); dataset.Tables[0].Clear(); sd.Dispose(); dataset.Dispose(); conn.Close(); } TimeSpan ts = DateTime.Now - begin; MessageBox.Show("ts = " + ts.TotalMilliseconds);
二.資料的更新
作者原話引出:
對於這個測試我插入10萬條資料用時28秒.效能還算可圈可點.但是對於批量更新,搜遍全球的例子,都是把記錄Fill到DataSet中然後牧舉rows
來更新,就我這個小資料量的測試而言,把10萬條資料Fill到DataSet中已經不能工作,如果是百萬,千萬如何操作?難道一定先把要批操作的記錄
先獲取到DataSet中?也就是我要更新哪些記錄就要選查詢這些記錄?
於是我仍然利用一個空的DataTable來加入要更新的記錄:
sd.SelectCommand = new SqlCommand("select devid,data_time,data_value from CurrentTest where 1=0", conn);
//1=0的條件保證取一個空表.
sd.UpdateCommand = new SqlCommand("update CurrentTest set data_time = @data_time,data_value = @data_value where devid = @devid", conn);
sd.UpdateCommand.Parameters.Add("@data_time", SqlDbType.Char, 19, "data_time");
sd.UpdateCommand.Parameters.Add("@data_value", SqlDbType.Int, 4, "data_value");
sd.UpdateCommand.Parameters.Add("@devid", SqlDbType.Char, 20, "devid");
sd.UpdateCommand.UpdatedRowSource = UpdateRowSource.None;
sd.UpdateBatchSize = 0;
for(int i=0;i<300;i++){
..............................
dataset.Tables[0].Rows.Add(row);
}
sd.Update(dataset.Tables[0]);
先更新300條試試,如果成功再迴圈更新所有記錄,但提示插入操作需要InsertCommand,因為一個空表然後Add Row操作,這時RowState是Added,
如果這時Update到資料庫,執行的就是插入操作而無法更新. 改成:
for(int i=0;i<300;i++){
..............................
row = {填入初始化的值};
dataset.Tables[0].Rows.Add(row);
}
dataset.AcceptChanges();
for(int i=0;i<300;i++){
..............................
dataset.Tables[0].Rows[i][x] = "xxxxxxx";
..............................
}
sd.Update(dataset.Tables[0]);
先在DataTable中插入資料,然後用AcceptChanges(),修改RowState為UnChanged,再修改表中資料希望改變UnChanged狀態,即將
DataTable從Current狀態改為Original,然後再對DataTable的Row進行更新,就能使
Update成功.但這樣做確實不方便.
調整思路,先從資料庫中取200條(批更新的Size大小),直接得到一個Original的DataTable.
sd.SelectCommand = new SqlCommand("select top 200 devid,data_time,data_value from CurrentTest", conn);
DataSet dataset = new DataSet();
sd.Fill(dataset);
用這200個空間來放要更新的其它資料看看:
for (int i = 0; i < 100; i++)
{
dataset.Tables[0].Rows[i].BeginEdit();
dataset.Tables[0].Rows[i]["data_time"] = "2222-22-22 22:22:22";
dataset.Tables[0].Rows[i]["data_value"] = 100;
dataset.Tables[0].Rows[i]["devid"] = "DEVID"+(i+10000);//更新DEVID10000到DEVID10200的記錄
dataset.Tables[0].Rows[i].EndEdit();
}
sd.Update(dataset.Tables[0]);
OK,成功,哈哈.把要更新的資料不斷往這個空間填,填滿就提交,這樣更新100000條資料只要幾個迴圈就行了.
DateTime begin = DateTime.Now; string connectionString = ""; using(SqlConnection conn = new SqlConnection(connectionString)){ conn.Open(); SqlDataAdapter sd = new SqlDataAdapter(); sd.SelectCommand = new SqlCommand("select top 200 devid,data_time,data_value from CurrentTest", conn); DataSet dataset = new DataSet(); sd.Fill(dataset); Random r = new Random(1000); sd.UpdateCommand = new SqlCommand("update CurrentTest " + " set data_time = @data_time,data_value = @data_value where devid = @devid", conn); sd.UpdateCommand.Parameters.Add("@data_time", SqlDbType.Char, 19, "data_time"); sd.UpdateCommand.Parameters.Add("@data_value", SqlDbType.Int, 4, "data_value"); sd.UpdateCommand.Parameters.Add("@devid", SqlDbType.Char, 20, "devid"); sd.UpdateCommand.UpdatedRowSource = UpdateRowSource.None; sd.UpdateBatchSize = 0; for (int count = 0; count < 100000;) { for (int i = 0; i < 200; i++,count++) { dataset.Tables[0].Rows[i].BeginEdit(); dataset.Tables[0].Rows[i]["data_time"] = "2222-22-22 22:22:22"; dataset.Tables[0].Rows[i]["data_value"] = 100; dataset.Tables[0].Rows[i]["devid"] = "DEVID"+count; dataset.Tables[0].Rows[i].EndEdit(); } sd.Update(dataset.Tables[0]); } dataset.Tables[0].Clear(); sd.Dispose(); dataset.Dispose