一、簡述
在項目中有一個需要導入數據包的需求,數據包是一個XML的文件,里面存儲有數據,那么讀取文件后就形成一個DataTable,然后改怎么把這個DataTable的數據批量插入到數據庫里面去呢?用一個循環?循環雖然簡單,但總結的有點別扭,所以還是用SqlCommandBuilder、SqlDataAdapter.update來批量插入數據吧。
二、內容
首先數據庫的原數據

然后批量插入數據的代碼
private string con = "Data Source=.;Initial Catalog=TestDatabase;Integrated Security=True"; private void DataBatchUpdate() { // 假數據 DataTable dt = new DataTable(); dt.Columns.Add("id", typeof(int)); dt.Columns.Add("testName"); DataRow dr = dt.NewRow(); dr["id"] = "1"; dr["testName"] = "白白"; dt.Rows.Add(dr); SqlConnection sqlCon = new SqlConnection(con); SqlDataAdapter sqlDa = new SqlDataAdapter("select * from testDataTable ", sqlCon); DataSet sqlds = new DataSet(); sqlDa.Fill(sqlds); // 數據庫數據 DataTable databaseData = sqlds.Tables[0]; databaseData.Merge(dt); SqlCommandBuilder sqlcb = new SqlCommandBuilder(sqlDa); sqlDa.Update(databaseData); }
得出來的數據,里面就新增了一條數據

這里主要是 Merge 起來合並兩張Table表,然后由SqlCommandBuilder與Update()來更新到數據。然而,函數Update() 是根據DataTable的RowState來更新表的。當用Merge合並了兩張表后,各行的RowState就像下圖
這里,先在原來代碼的基礎添加幾行代碼
private string con = "Data Source=.;Initial Catalog=TestDatabase;Integrated Security=True"; private void DataBatchUpdate() { // 假數據 DataTable dt = new DataTable(); dt.Columns.Add("id", typeof(int)); dt.Columns.Add("testName"); DataRow dr = dt.NewRow(); dr["id"] = "1"; dr["testName"] = "白白"; dt.Rows.Add(dr); SqlConnection sqlCon = new SqlConnection(con); SqlDataAdapter sqlDa = new SqlDataAdapter("select * from testDataTable ", sqlCon); DataSet sqlds = new DataSet(); sqlDa.Fill(sqlds); // 數據庫數據 DataTable databaseData = sqlds.Tables[0]; databaseData.Merge(dt); // 顯示表格沒一行的狀態 databaseData.Columns.Add("updatedSate"); for (int i = 0; i < databaseData.Rows.Count; i++) { DataRow updatedRow = databaseData.Rows[i]; updatedRow["updatedSate"] = updatedRow.RowState; } //SqlCommandBuilder sqlcb = new SqlCommandBuilder(sqlDa); //sqlDa.Update(databaseData); gridData.DataSource = databaseData; gridData.DataBind(); }
得出的結果則顯示最后一條的狀態是 Added,所以就作為新數據插入到數據庫去。

那么,如果只是批量插入數據的話
SqlDataAdapter sqlDa = new SqlDataAdapter("select * from testDataTable ", sqlCon);
還可以這么寫,就是獲取到數據庫表中的結構就可以了。
SqlDataAdapter sqlDa = new SqlDataAdapter("select * from testDataTable where 1=2", sqlCon);
那么,如果只是單純的批量插入數據庫就簡單多了,可是項目的導入數據包功能,如果用戶是重復導入了呢?又或者導入的數據當中只有幾個單元格的數據跟數據庫的數據不同的呢?這該怎么解決?嗯??在代碼中寫個幾句代碼判斷導入的數據在數據庫表中是否存在,存在就把數據庫表中的數據刪掉,再新插入進去? - - ! 顯然不靠譜。
后來就發現了有一種很神奇的方法,因為代碼中的Update()是根據RowState來判斷是否增刪改的,上面只用到了“增”,那么只要RowsState是“改”就可以了。
首先代碼
private string con = "Data Source=.;Initial Catalog=TestDatabase;Integrated Security=True"; private void DataBatchUpdate() { // 假數據 DataTable dt = new DataTable(); dt.Columns.Add("id", typeof(int)); dt.Columns.Add("testName"); DataRow dr = dt.NewRow(); dr["id"] = "1"; dr["testName"] = "白白"; dt.Rows.Add(dr); SqlConnection sqlCon = new SqlConnection(con); SqlDataAdapter sqlDa = new SqlDataAdapter("select * from testDataTable ", sqlCon); DataSet sqlds = new DataSet(); sqlDa.Fill(sqlds); // 數據庫數據 DataTable databaseData = sqlds.Tables[0]; databaseData.PrimaryKey = new DataColumn[] { databaseData.Columns["id"] }; //設置DataTable的主鍵 databaseData.Merge(dt); // 顯示表格沒一行的狀態 databaseData.Columns.Add("updatedSate"); for (int i = 0; i < databaseData.Rows.Count; i++) { DataRow updatedRow = databaseData.Rows[i]; updatedRow["updatedSate"] = updatedRow.RowState; } SqlCommandBuilder sqlcb = new SqlCommandBuilder(sqlDa); sqlDa.Update(databaseData); gridData.DataSource = databaseData; gridData.DataBind(); }
關鍵是為DataTable設置主鍵,然后Merge()就會自動修改,其RowState就變成了“改”,並且Name也隨之變了。
《=修改后
《=修改前
這樣就可以實現在相同的ID下自動批量更新數據的效果。 注:Update()更新數據的時候,數據庫表中結構要有主鍵才可以。
