相關知識:
- DataSet中的數據一旦從數據庫下載下來,便不再與數據庫保持聯系。如果修改了DataSet中的數據,需要重新建立連接,並且通過SQL命令將修改更新到數據庫去
- 編寫SQL命令往往比較繁瑣和機械化,ADO.NET提供了一個SqlCommandBuilder對象,幫助DataAdapter對象從SELECT語句推算出需要的UPDATE,DELETE和INSERT語句;然后DataAdapter便可以利用這些語句,檢查DataSet中被修改的數據,然后提交到數據庫
- SqlCommandBuilder自動生成的SQL命令雖然方便,但卻不靈活。尤其是在需要向多個表中寫入數據的時候,往往需要自定義增刪改語句
代碼示例:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Data; 7 using System.Data.SqlClient; 8 9 namespace ConsoleApplication11 10 { 11 class Program 12 { 13 static void Main(string[] args) 14 { 15 string strConn = @"server=Joe-PC;database=AccountDBforSQLInjection;uid=sa;pwd=root"; 16 SqlConnection conn = new SqlConnection(strConn); 17 18 string sql = "SELECT AccountID,AccountName,password FROM Account"; 19 SqlDataAdapter da = new SqlDataAdapter(sql, conn); 20 21 DataSet ds = new DataSet(); 22 23 da.Fill(ds, "Account"); 24 25 Console.WriteLine("Account表中原有數據:"); 26 27 DataTable dt = ds.Tables["Account"]; 28 DataView dv = new DataView(dt); 29 dv.Sort = "AccountID ASC"; 30 31 foreach (DataRowView drv in dv) 32 { 33 Console.WriteLine("{0}:{1},{2}", drv[0], drv[1], drv[2]); 34 } 35 36 Console.WriteLine(""); 37 38 //添加一行數據——Insert 39 DataRow newRow = dt.NewRow(); //根據Table的架構,創建一個新的空行 40 // 給新行賦值 41 newRow["AccountID"] = 4; 42 newRow["AccountName"] = "new"; 43 newRow["password"] = "123456"; 44 // 將新行加到表的行集合中 45 dt.Rows.Add(newRow); 46 47 //修改一行數據——Update 48 DataRow updateRow = dt.Rows[0]; //修改表中第一行數據 49 updateRow["password"] = "000000";//修改了密碼為000000 50 51 //刪除一行數據——Delete 52 DataRow deleteRow = dt.Rows[1];//准備刪除原表中第二行數據 53 dt.Rows.Remove(deleteRow); 54 55 //測試內存中數據 56 Console.WriteLine("修改后,Account表中現有數據"); 57 foreach (DataRowView drv in dv) 58 { 59 Console.WriteLine("{0}:{1},{2}", drv[0], drv[1], drv[2]); 60 } 61 62 //程序在此暫停等待用戶輸入,檢查數據庫,newRow此時尚未插入到數據庫中。 63 //此時newRow僅僅是在DataSet對象內存中創建,並為更新到數據庫 64 Console.WriteLine(""); 65 Console.WriteLine("檢查數據庫中是否已經創建了新行,然后按回車繼續。"); 66 Console.ReadLine(); 67 68 //更新到數據庫 69 //創建SqlCommandBuilder,並且把DataAdapter對象傳入。 70 SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(da); 71 Console.WriteLine("生成的Insert語句:{0}", cmdBuilder.GetInsertCommand().CommandText); 72 Console.WriteLine("生成的Update語句:{0}", cmdBuilder.GetUpdateCommand().CommandText); 73 //之前建DataAdapter時候的sql語句,SELECT的鍵列,必須含有主鍵,此處SqlCommandBuilder的update才能成功 74 Console.WriteLine("生成的Delete語句:{0}", cmdBuilder.GetDeleteCommand().CommandText); 75 //執行更新 76 da.Update(dt);//將table中的所有修改更新到數據庫 77 Console.WriteLine("數據更新到數據庫。檢查數據庫中是否已經更新了數據。"); 78 79 Console.WriteLine(""); 80 81 //重新輸出數據庫中數據,檢測以上操作是否成功 82 string _sql = "SELECT AccountID,AccountName,password FROM Account"; 83 SqlDataAdapter _da = new SqlDataAdapter(_sql, conn); 84 _da.Fill(ds, "newAccount"); 85 Console.WriteLine("Account表中現有數據:"); 86 87 DataTable _dt = ds.Tables["newAccount"]; 88 DataView _dv = new DataView(_dt); 89 _dv.Sort = "AccountID ASC"; 90 91 foreach (DataRowView drv in _dv) 92 { 93 Console.WriteLine("{0}:{1},{2}", drv[0], drv[1], drv[2]); 94 } 95 96 Console.WriteLine(""); 97 } 98 } 99 }
程序分析:
- 在DataSet中修改數據,僅是改了程序內存中的數據,並不會影響到數據庫
- 通過SqlCommandBuilder幫助構建增刪改的SQL語句。通過打印這些語句命令,可以看出,它們是用過參數來執行SQL命令的。當正式更新數據時,會用DataSet中的修改后的數據來填充這些參數值
- 調用SqlDataAdapter對象的Update方法,正式將數據更新到數據庫
擴展問題:
如果在Fill一個DataSet時的SQL語句是同時從多個表中聯合查詢的數據,那么要更新數據時,插刪改的語句將如何生成呢?