使用ADO.NET輕鬆操縱資料庫(二)

javaprogramers發表於2005-04-21
    首先,ADO.NET中使用了DataAdapter 來處理與資料庫的聯機與離線。當時開發人員設計了DataAdapter是為了能夠處理離線資料,方便操作,關於這一點,只要呼叫其Fill()方法即可,這時會在DataSet中建立一個新的名為“Table“的DataTable.要重新指定名可用DataAdapter.Fill(DataSet,“Tabelname“)。此時connection也關閉了。DataAdapter既可以用來提交查詢,並將結果儲存到DataSet中,也可以用來向資料庫傳遞更改。僅僅使用其Update方法即可達到向資料庫提交儲存地DatSet中的更改。

    DataAdapter將查詢的結果儲存在DataSet或DataTable物件中,當執行這一過程的時候,DataAdapter使用了一個Command來與資料庫通訊,並在內部使用了DataReader來獲取查詢結果,最後才將結果複製到DataSet新行中去。這也是Fill的過程。如果有兩個DataAdapter物件,都使用相同的Connection物件,在建立的時候就會建立兩個Connection物件,而不是同一個,這種情況的解決方案是:


   SqlConnection con=new SqlConnection("server=localhost;database=Northwind;Trusted_Connection=Yes;")
   SqlDataAdapter da=new SqlDataAdapter("select CategoryID,Description from Categories",con);
   SqlDataAdapter da=new SqlDataAdapter("select CategoryID,Description from Customers",con);

而不是將查詢字串,單獨寫成一行。

   有時候可能並不希望DataSet中的架構與資料庫中的架構相同,這種情況的解決方案之一是可以採用別名的方法,即select id as Product ID,amount as Product Amount from product;另外一種解決方案就是使用DataAdapter提供的TableMappings集合機制,通過它就可以將查詢結果對映到DataSet結構中,這種方法更方便,更靈活。TableMappings屬性返回一個DataTableMappingsCollection物件,其中包含了一組DataTableMappings,只要DataSet中相應的表名稱與資料庫中的表名相同,即可以使用它來建立一個對映(DataSet中可以有多個表)。TableMappings裡還有一個ColumnMappings屬性,其用法與TableMappings相似。其原理是DataAdapter從資料庫讀取資料後,利用DataReader從結果集中獲取列名稱,有一點特別要注意,即只能獲取列名稱而無法獲取表名稱,DataAdapter事先假定表名稱為Table,接著遇到對映語句則進行表對映。不說了,看程式碼:

  DataColumnMapping colMap;
   SqlConnection con=new SqlConnection("server=localhost;database=Northwind;Trusted_Connection=Yes;");
   SqlDataAdapter da=new SqlDataAdapter("select CategoryID,Description from Categories",con);
   DataSet ds=new DataSet();

   DataTableMapping tblMap=da.TableMappings.Add("Table","Ca"); //這裡Table為關鍵,對映表名為Ca

   colMap=tblMap.ColumnMappings.Add("CategoryID","ID"); //對映列表
   colMap=tblMap.ColumnMappings.Add("Description","描述");
   // Response.Write(tblMap.DataSetTable.ToString());
    da.Fill(ds);
   DataTable dt=ds.Tables["Ca"]; //這裡是對映後的表名,如果仍為資料庫的表名,則無效,特別注意
   this.DataGrid1.DataSource=dt;
   this.DataGrid1.DataBind();

執行程式碼後就會發現DataGrid1上的列名為ID和描述 (^_^)

(注:使用DataTableMapping 之前要前匯入名空間System.Data.Common;)

還可以使用AddRange方法來簡化表和列的對映:(一些程式碼同上面)

  .......                
   DataTableMapping tblMap=da.TableMappings.Add("Table","Ca");       DataColumnMapping[] colMapArray=new DataColumnMapping[]{new DataColumnMapping("CategoryID","產   品號"),new DataColumnMapping("Description","描述")};        tblMap.ColumnMappings.AddRange(colMapArray);     
   ......                  

這種對映關係只能從資料庫中讀取展示給使用者,如果要將對映後的Table的更改提交給資料庫,這時庫發現其中列與庫中列不同,便會發生異常,DataAdapter 同時也提供了MissingMappingAction屬性來處理。

DataAdapter1.MissingMappingAction=MissingMappingAction.Passthrough/Ignore/Error

它接受MissingMappingAction的列舉值,Passthrough這個值表示如果在庫中找不到與DataSet中相同列的話,就將此列對映到庫中,Ignore列舉值表示忽略示出現的列,Error表示找不到相應的列則丟擲異常。

分頁:

分頁在應用中是常有的事,而DataAdapter本身也提供了分頁的簡單功能,如:DataAdapter1.Fill(dataset,startrow,rownum,“tablename“)這種功能用於資料量較小的查詢就可以,但當有大量資料的時候,就會發現這種分頁的問題的存在。它的原理是假如有一百行資料,分成十頁,每頁十行,當獲取每一頁的時候,返回前10行,再接著,第二頁,刪除了前10行而獲取接下的10行,在這一次中,只是為了獲取10行資料,但資料庫卻返回了20行,依此類推,第10頁的時候就會返回100行,而DataAdapter本身就幫我們刪除了90行,因為我們看上去返回的還是10行,這種效能太低。因此本篇繼續介紹另外一種效能較高的分頁方法。實際上這種分頁方法是將上一頁最後一行的鍵值儲存下來,直接在SQL語句中就過濾掉了,不象前面那種到DataAdapter這邊才過濾掉。例:

con=new SqlConnection("server=localhost;database=Northwind;Trusted_Connection=Yes;");
da=new SqlDataAdapter("select top 50 CustomerID,CompanyName from Customers where CustomerID>'BOTTM'",con); 
ds=new DataSet();
da.Fill(ds,"Categories");
this.DataGrid1.DataSource=ds.Tables["Categories"]; this.DataGrid1.DataBind();
con.Close();

這裡假如上一頁最後一個鍵值為”BOTTM”,可以將它用引數替代掉,這樣就查出了在'BOTTM'之後的50行。這種方法實現簡單效率也高。

相關文章