C#中SqlDataAdapter的使用小結
SqlDataAdapter概述
SqlDataAdapter是 DataSet和 SQL Server之間的橋接器,用于檢索和儲存資料。SqlDataAdapter通過對資料源使用适當的Transact-SQL語句映射 Fill(它可更改DataSet中的資料以比對資料源中的資料)和 Update(它可更改資料源中的資料以比對 DataSet中的資料)來提供這一橋接。當SqlDataAdapter填充 DataSet時,它為傳回的資料建立必需的表和列(如果這些表和列尚不存在)。
)我們可以通過以下三種方法來建立SqlDataAdapter對象:
使用方法
1、通過連接配接字元串和查詢語句
string strConn="uid=賬号;pwd=密碼;database=資料庫;server=伺服器";//SQL Server連結字元串
strSql="SELECT * FROM 表名";
SqlDataAdapter da=new SqlDataAdapter(strSql,strConn);
DataSet ds=new DataSet();//建立DataSet執行個體
da.Fill(ds,"自定義虛拟表名");//使用DataAdapter的Fill方法(填充),調用SELECT指令
這種方法有一個潛在的缺陷。假設應用程式中需要多個SqlDataAdapter對象,用這種方式來建立的話,會導緻建立每個SqlDataAdapter時,都同時建立一個新的SqlConnection對象,方法二可以解決這個問題
2、通過查詢語句和SqlConnection對象來建立
-
string strConn="uid=賬号;pwd=密碼;database=資料庫;server=伺服器";//SQL Server連結字元串
-
SqlConnection conn=new SqlConnection(strConn);
-
string strSql="SELECT * FROM 表名";
-
SqlDataAdapter da = new SqlDataAdapter(strSql, conn);
-
DataSet ds=new DataSet();//建立DataSet執行個體
-
da.Fill(ds,"自定義虛拟表名");//使用DataAdapter的Fill方法(填充),調用SELECT指令
3、通過SqlCommand對象來建立
-
string strConn="uid=賬号;pwd=密碼;database=資料庫;server=伺服器";//SQL Server連結字元串
-
SqlConnection connSql=new SqlConnection (strConn); //Sql連結類的執行個體化
-
connSql.Open ();//打開資料庫
-
//使用SqlDataAdapter時沒有必要從Connection.open()打開,
-
//SqlDataAdapter會自動打開關閉它。
-
string strSql = "SELECT * FROM 表名"; //要執行的SQL語句
-
SqlCommand cmd=new SqlCommand(strSql,connsql);
-
SqlDataAdapter da=new SqlDataAdapter(cmd); //建立DataAdapter資料擴充卡執行個體
-
DataSet ds=new DataSet();//建立DataSet執行個體
-
da.Fill(ds,"自定義虛拟表名");//使用DataAdapter的Fill方法(填充),調用SELECT指令
-
ConnSql.Close ();//關閉資料庫
SqlDataAdapter da=new SqlDataAdapter(strSQL,ConnSql); //建立DataAdapter資料擴充卡執行個體DataSet ds=new DataSet();//建立DataSet執行個體da.Fill(ds,"自定義虛拟表名");//使用DataAdapter的Fill方法(填充),調用SELECT指令ConnSql.Close ();//關閉資料庫
注意
如果隻需要執行SQL語句或SP,就沒必要用到DataAdapter ,直接用SqlCommand的Execute系列方法就可以了。sqlDataadapter的作用是實作Dataset和DB之間的橋梁:比如将對DataSet的修改更新到資料庫。
SqlDataAdapter的UpdateCommand的執行機制是:當調用SqlDataAdapter.Update()時,檢查DataSet中的所有行,然後對每一個修改過的Row執行SqlDataAdapter.UpdateCommand ,也就是說如果未修改DataSet中的資料,SqlDataAdapter.UpdateCommand不會執行。
使用要點
1、SqlDataAdapter内部通過SqlDataReader擷取資料,而預設情況下SqlDataReader不能獲知其查詢語句對應的資料庫表名,
是以下面的代碼:
-
string strConn = "uid=賬号;pwd=密碼;database=資料庫;server=伺服器";//SQL Server連結字元串
-
strSql="SELECT * FROM 表名";
-
SqlDataAdapter da = new SqlDataAdapter(strSql,strConn);
-
DataSet ds = new DataSet();
-
da.Fill(ds);
會在DataSet中建立一個新的DataTable,這個新的DataTable會擁有名為CustomerID和CompanyName 列,但是DataTable對象的名稱是Table,而不是我們希望的Customers。
這個問題,可以通過添加TableMapping來解決:
-
string strConn="uid=賬号;pwd=密碼;database=資料庫;server=伺服器";//SQL Server連結字元串
-
strSql="SELECT * FROM 表名";
-
SqlDataAdapter da=new SqlDataAdapter(strSQL,strConn);
-
da.TableMappings.Add("Table","Customers"); // 設定對象名稱
-
DataSet ds=new DataSet();
-
da.Fill(ds);
其實最簡潔的方法是通過使用Fill方法的重載,通過指定DataTable,像這樣:
SqlDataAdapter.Fill(DataSet,"MyTableName");
這樣就可以不必使用TableMappings集合。
2、在使用Fill方式時,可以指定DataTable,而不是DataSet:
-
string strConn="uid=賬号;pwd=密碼;database=資料庫;server=伺服器";//SQL Server連結字元串
-
strSql="SELECT * FROM 表名";
-
SqlDataAdapter da = new SqlDataAdapter(strSql, strConn);
-
DataTable tbl=new DataTable( );
-
da.Fill(tbl);
3、注意打開和關閉連接配接的處理
在調用SqlCommand對象執行sql指令之前,需要保證與該對象關聯的SqlConnection對象時打開的,否則SqlCommand的方法執行時将引發一個異常,但是我們在上面的代碼中看到,SqlDataAdapter沒有這樣的要求。
如果調用SqlDataAdapter的Fill方法,并且其SelectCommand屬性的SqlConnection是關閉狀态,則SqlDataAdapter會自動打開它,然後送出查詢,擷取結果,最後關閉連接配接。如果在調用Fill方法前,SqlConnection是打開的,則查詢執行完畢後,SqlConnection還将是打開的,也就是說SqlDataAdapter會保證SqlConnection的狀态恢複到原來的情形。
這有時會導緻性能問題,需要注意,例如下面的代碼:
-
string strConn="uid=賬号;pwd=密碼;database=資料庫;server=伺服器";//SQL Server連結字元串
-
SqlConnection conn=new SqlConnection(strConn);
-
SqlDataAdapter daCustomers,daOrders;
-
strSql="SELECT * FROM Customers";
-
daCustomers = new SqlDataAdapter(strSql, conn);
-
strSql="SELECT * FROM Orders";
-
daOrders=new SqlDataAdapter(strSql, conn);
-
DataSet ds=new DataSet();
-
daCustomers.Fill(ds,"Customers");
-
daOrders.Fill(ds,"Orders");
以上代碼會導緻連接配接被打開和關閉兩次,在調用Fill方法時各一次。為了避免打開和關閉SqlConnection對象,在調用SqlDataAdapter對象的Fill方法之前,我們可以先打開SqlConnection對象,如果希望之後關閉連接配接,我們可以再調用Close方法,就像這樣:
-
cn.Open();
-
daCustomers.Fill(ds,"Customers");
-
daOrders.Fill(ds,"Orders");
-
cn.Close();
4、多次調用Fill方法需要注意資料重複和有效更新資料的問題
-
string strConn="uid=賬号;pwd=密碼;database=資料庫;server=伺服器";//SQL Server連結字元串
-
strSql="SELECT * FROM Customers";
-
SqlDataAdapter da=new SqlDataAdapter(strSql, strConn);
-
DataSet ds=new DataSet();
-
da.Fill(ds,"Customers");
-
//…….
-
da.Fill(ds,"Customers");
我們分析上面的代碼,通過兩次調用Fill方法,SqlDataAdapter執行兩次查詢,并兩次将查詢結果儲存到DataSet中,第一次調用在DataSet中建立了一個名為Customers的新表。第二次調用Fill方法将查詢的結果追加到DataSet中的同一個表中,是以,每個客戶的資訊将在DataSet中出現兩次!當然,如果資料庫管理者對Customers表定義了主鍵,則SqlDataAdapter在天成DataTable時,會判斷重複行,并自動丢棄掉舊的值。
考慮一下,假定一個特定客戶在第一次調用Fill方法時,存儲于資料庫中,那麼SqlDataAdapter會将其添加到建立的DataTable中。如果後來這個客戶被删除了,那麼第二次調用Fill方法時,SqlDataAdapter将不會在查詢結果中找到該客戶資訊,但是它也不會将客戶資訊從DataSet中删除。這就導緻了資料更新的問題。
是以推薦的做法是,在調用Fill方法前,先删除本地DataSet中緩存的資料!