ADO.NET系列之DataAdapter物件
我們前兩篇文章介紹了ADO.NET的概念,以及介紹了Connection和Command物件,基本的增刪改查操作都能夠實現了,本節再介紹一個強大的DataAdapter物件。
我們先來看看DataAdapter物件的工作原理如下圖所示:
DataAdapter首先將構造一個SelectCommand例項(本質就一個Command物件),然後檢查是否開啟連線,如果沒有開啟連線則開啟連線,緊接著呼叫DataReader介面檢索資料,最後根據維護的對映關係,將檢索到得資料庫填充到本地的DataSet或者DataTable中。同理,我們需要更新資料來源時,DataAdatper則將本地修改的資料,跟據對映關係,構造InsertCommand,UpdateCommnad,DeleteCommand物件,然後執行相應的命令。
為什麼說DataAdapter物件強大呢?首先DataAdapter物件可以執行查詢操作,嚴格意義上也不是執行,而是可以填充DataSet,DataTable物件,再一個DataAdapter物件可以進行批量更新和批量刪除,至於批量新增我們有SqlBulkCopy物件,後面文章會介紹SqlBulkCopy物件。
DataAdapter.Net提供了四種Connection 物件:
- 針對Sql Server的SqlDataAdapter,位於名稱空間System.Data.SqlClient下
- 針對Oledb連結的OledbDataAdapter,位於名稱空間System.Data.Oledb下
- 針對MySql的MySqlDataAdapter,位於名稱空間System.Data.MySqlClient下(需要引用MySql.Data.dll)
- 針對Oracle的OracleDataAdapter,位於名稱空間Oracle.ManagedDataAccess.Client(需引用Oracle.ManagedDataAccess.dll)
我們先來看看DataAdapter物件填充DataSet,DataTable物件的示例:
string connectionString = "Data Source=.;Initial Catalog=ax_log;User Id=sa;Password=sa123;"; using (SqlConnection con = new SqlConnection(connectionString)) { string sql = "select * from eftest where [email protected]"; SqlParameter para = new SqlParameter("@id", 1); using (SqlCommand com = new SqlCommand(sql, con)) { DataSet ds = new DataSet(); try { com.Parameters.Add(para); con.Open(); SqlDataAdapter adapter = new SqlDataAdapter(com); adapter.Fill(ds); foreach (DataRow s in ds.Tables[0].Rows) { Console.WriteLine("ID:"+s["id"].ToString()); Console.WriteLine("Name:" + s["name"].ToString()); } } catch (Exception ex) { } } }
DataAdapter物件實現批量修改
string connectionString = "Data Source=.;Initial Catalog=ax_log;User Id=sa;Password=sa123;"; using (SqlConnection con = new SqlConnection(connectionString)) { string sql = "select * from eftest "; DataSet ds = new DataSet(); try { con.Open(); SqlDataAdapter adapter = new SqlDataAdapter(sql, con); adapter.Fill(ds);//填充ds for (int k = 0; k < ds.Tables[0].Rows.Count; k++) { Console.WriteLine(ds.Tables[0].Rows[k].RowState);//RowState:Unchanged Console.WriteLine(ds.Tables[0].Rows[k][1]); ds.Tables[0].Rows[k][1] = "abc";//每一行的第二列都修改為abc Console.WriteLine(ds.Tables[0].Rows[k][1]); Console.WriteLine(ds.Tables[0].Rows[k].RowState);//RowState:Modified } SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(adapter);//這行不能缺少,除非自定義Command賦值給adapter.UpdateCommand Console.WriteLine("生成的Update語句:{0}", cmdBuilder.GetUpdateCommand().CommandText); adapter.Update(ds);//更新到資料來源中 ds.AcceptChanges();//提交到DataTable中 提交後DataRow.RowState會修改為Unchanged } catch (Exception ex) { Console.WriteLine(ex.Message); } }
根據上程式碼,我們先要介紹下DataRow.RowState屬性,DataRowState是一個列舉型別:
// // 摘要: // 該行已被建立,但不屬於任何 System.Data.DataRowCollection。System.Data.DataRow 在以下情況下立即處於此狀態:建立之後新增到集合中之前;或從集合中移除之後。 Detached = 1, // // 摘要: // 該行自上次呼叫 System.Data.DataRow.AcceptChanges 以來尚未更改。 Unchanged = 2, // // 摘要: // 該行已新增到 System.Data.DataRowCollection 中,System.Data.DataRow.AcceptChanges 尚未呼叫。 Added = 4, // // 摘要: // 該行已通過 System.Data.DataRow 的 System.Data.DataRow.Delete 方法被刪除。 Deleted = 8, // // 摘要: // 該行已被修改,System.Data.DataRow.AcceptChanges 尚未呼叫。 Modified = 16
我們可以根據RowState屬性可以很清楚的知道DataTable中的每一行資料是新增的?修改過?刪除了?還是未曾改變! 其實adapter.Update(ds)更新資料也是根據這個屬性批量向資料來源更新的。
DataAdapter實現批量新增和批量刪除都是大同小異,只是操作DataTable新增或者刪除就行了。