数据访问模式二:数据集和数据适配器(传统的数据访问模式)
上一篇文章介紹了使用DataSource控件訪問數據庫的過程,本節介紹利用數據適配集/數據適配器的訪問數據庫。這兩種設計模式的差別,使得GridView的設計即要支持DataSource控件的數據綁定模式,還需要支持數據集和數據適配器這種數據綁定模式,由于這對峰巒冤孽的存在,才讓GirdView控件的設計時較為復雜。當然天天感覺,你只要知道這兩種差別并具有一些概念就可以了,也不用深究,畢竟大家不是控件開發專家。
2.4數據集與數據適配器
VS.NET2005支持傳統的數據綁定方式,并為該方式提供了可視化操作,本級將介紹數據集和數據適配器。
2.4.1強類型化數據集簡介
對于大多數應用程序而言,不管將來應用于Web Server上還是Windows Form上,數據訪問都是一個重要的環節。數據訪問更傾向于處理對數據庫的讀寫,您可以單獨創建Helper類來處理這些共性,但是您仍然需要編寫大量的代碼。
事實上,我們可能有這樣一種感覺:創建數據訪問層很乏味,因為對于 DAL 的不同方法,執行 SQL 語句或存儲過程的 ADO.NET 代碼通常是相同或相似的。盡管可以使用本書前面的方法自定義 ADO.NET 代碼編寫自己的 DAL,但是Visual Studio 還是提供了一種方便的方式,可以根據簡單向導的輸入生成數據訪問層。這種情況下的數據訪問層是強類型 的DataSet 對象。DataSet 包含 TableAdapter 類型,這些類型公開用于返回強類型 DataTable 對象的方法。這些方法適合用于直接綁定到 ObjectDataSource,也適合用于從業務邏輯層組件進行調用。
?
1)類型化數據集
VS.NET2005提供了數據集和數據適配器,使用它們可以大大減少代碼的編寫,利用Visual Stduio.NET 設計器可以以聲明的方式生成強類型化數據集。這里的數據集也是從ADO.NET? DataSet,DataTable和DataRow派生的類,該類對外界提供了安全的API接口。通過API接口使得我們可以很容易訪問DataSet里的數據與數據模式。
可以通過在VS.NET2005里通過簡單的拖、放操作來生成這些強類型數據集,利用屬性設計器還可以建立數據訪問模式。其實您的這些操作就是生成一個類型化的XML模式文件定義(XML Schema Definition,XSD)。改XSD文件包含了數據庫設計模式結構,系統能夠根據該結構來將數據包含在DataSet中,換句話說,VS.NET2005將使用該XSD文件來生成一個包含數據集類定義的代碼文件。
??? 當你在應用程序里訪問數據時,數據將根據數據表的不同被組織為一個個業務邏輯實體,例如Category實體,Product實體等(數據適配器表),為了能夠使用這些數據,您需要將這些邏輯實體轉換為類的對象,所以您可以自己為每一個實體編寫一個類對象。這些實體對象一般會為數據訪問提供一些屬性和方法,您可以在類里使用這些屬性和方法以返回強類型集合
強類型化的數據集為建立和委托自定義類對象提供了方便,從本質上說您建立的類對象是一個類型化的DataSet,該DataSet包含了業務邏輯實體和一些數據集合,但是主要區別是您在以聲明的方式編寫模式文件,您可以利用VS.NET2005的支持以可視化的方式編輯,刪除XML數據模式文件,VS.NET能夠感知模式文件的變化并更新代碼文件類的成員。
另外,由于強類型化DataSet是從ADO.NET相關類派生,所以您可以重復利用ADO.NET提供的數據操作能夠,例如數據綁定,數據分頁、排序、過濾等常見的工作。
最后一點,也是最重要的一點當您在VS.NET2005建立數據集后,您可以為每一張表獲取強類型的數據適配器表,使用該數據適配器您可以極大的減少常規代碼大編寫。該數據適配器進一步封裝了數據的鏈接Connection,數據的執行Command,后面會詳細介紹這些內容。
?
2) DataSets和Business Objects的比較
?? 一個常見的討論是:是否在應用程序里使用DataSets。雖然DataSets確實為應用程序代碼的編寫提供了方便,但是由于它封裝了許多實現細節,因為在理解性和可控性方面都具有一定的局限性。在這方面自定義Business Objects具有可度性強,理解簡單的有點。但是正如前述,DataSets可以減類似代碼的重復編寫。事實上,對于Web而言,數據的讀取原比數據的寫入占有重要的比例,所以在這簡單的數據讀取方面,DataSets將比Business Objects更具有優勢。???
?
2.4.2 建立數據集與數據適配器
??? 本書在第一章曾介紹如何利用VS.NET2005建立數據庫,本節繼續使用Database數據庫來說明數據集和數據適配器的使用。在“Server Explorer”視圖里,您可以看到Database數據庫里已經有了Categories和products兩張表,如圖2-42。
??
圖2-42 Database數據庫??????????????
?
?
1) 使用DataSet設計器
接下來我們將建立Database的業務邏輯層,在“解決方案資源管理器”里單擊鼠標右鍵選擇“Add New Item...”,選擇“DataSet”并將它命名Database.xsd如圖2-43。
在VS.NET里建立的DataSet將采用默認的文件命名方式。例如此處建立的文件名為Database.xsd,則系統以后建立的DataSet派生類就命名為Database。相反,如果您此處建立的DataSet命名為MyDAL,則以后建立的DataSet派生類就命名為MyDAL類。
接下來會彈出一個對話框,詢問你是否將該文件添加到App_Code目錄下,我們選擇“Yes”以便后面代碼共享。
注意:App_Code文件夾除了類文件*.cs外,*.XSD,Web Service等也都可以共享
此后,系統將在App_Code目錄下建立Database.xsd文件并啟動“TableAdapter Configuration Wizard”向導如圖2-44圖2-44 TableAdapter Configuration Wizard”向導
?
2) 建立第一個數據適配器
??? 在圖2-44里,單擊Next,系統會詢問你是否使用DatabaseConnectionString作為連接字符串并保存在web.config里,選中“Yes”復選框如
?引入下一步,選擇SQL語句的命令類型,可以是SQL語句,也可以新建存儲過程或者是已經存在的存儲過程。在這里我們使用第一項“Use SQL statements”,如圖2-26。
圖2-46 使用SQL語句
?
在下一步里,我們使用“Query Builder”來建立SQL語句,如圖2-47,你可以單擊“Execute Query”來查看該SQL語句執行的結果。
圖2-47 Query Builder查詢器
?
當返回后將自生成如下的SQL語句,參考圖2-48。
SELECT???? ProductID, ProductName, CategoryID, Price, InStore, Description
FROM???????? Products
??????????????????????? 圖2-48 生成SQL語句
?
在圖2-48里還有一個“Advanced Options...”(高級選項),單擊后將彈出高級選項對話框,如圖2-49
圖2-49 高級對話框
在高級選項里,默認是選中“Generate Insert,Update And Delete statements”的,所以系統會根據Select語句自動生成相應的插入、更新和刪除語句,而“Use optimistic concurrency”(沖突檢測)和Refresh the data table(刷新表格數據)是不選中的。
單擊Next,將進入“Choose Methods to Generate”頁面,在該頁面系統會讓我們命名在業務邏輯處理中的方法名稱,這里有兩類方法模式:
Fill類:DataSet將使用Fill類生成一個以DataSet或者DataTable作為參數的方法,該方法將使用前面生成的SQL語句來填充數據集。
Get類:該類方法用來獲取前面SQL語句或者存儲過程執行的返回結果值。
圖2-50顯示了我的設定,其中Fill類使用的是Fill方法,而Get類命名的方法是GetAllProducts。
另外我還選中了下面的GenerateDBDirectMethods,這樣系統將自動根據我前面的Insert、Update和Delete語句生成相應的方法。
單擊“Next”會顯示系統自動生成的結果,如果成功了,可以單擊Finish之間完成該向導。
?
在圖2-51上單擊鼠標右鍵,選擇“View Code“,我們可以查看系統自動生成的XSD源代碼,下面我們看看系統都生成了哪些代碼
1、 使用Connection標識數據庫連接
在前面向導里數據庫的連接配置是通過Connections的Connection表示的,這種配置會映射在XSD文檔里,如代碼2-21。正如您所看到的,數據庫鏈接還包括了Name、Provider等屬性,它們都用于以后數據庫的連接。
??????? <Connections>
????????? <Connection
AppSettingsObjectName="Web.config"
AppSettingsPropertyName="DatabaseConnectionString"
ConnectionStringObject=""
IsAppSettingsProperty="True"
Modifier="Assembly"
Name="DatabaseConnectionString (Web.config)"
ParameterPrefix="@"
PropertyReference="AppConfig.System.Configuration.ConfigurationManager.0.ConnectionStrings.DatabaseConnectionString.ConnectionString"
Provider="System.Data.SqlClient">
????????? </Connection>
??????? </Connections>
???????????? ?代碼2-21 Database.xsd代碼片段(1)
?
2、數據的執行用XXXCommand表示(這里是偶的解釋,可以跳過)
?? 在前面的SQL語句向導里,由于要求系統根據Select語句自動生成Delete、Update和Insert語句以及方法,所以系統將使用<SelectCommand>、<DeleteCommand>、<UpdateCommand>和<InsertCommand>來表示這些方法,并建立這些方法所需要的參數,如2-22。
???? ?<DbSource
ConnectionRef="DatabaseConnectionString (Web.config)"
DbObjectName="dbo.Products" DbObjectType="Table"
FillMethodModifier="Public"
FillMethodName="Fill" ??????????????????????GenerateMethods="Both"
GenerateShortCommands="True" ??????????GeneratorGetMethodName="GetAllProducts"
GeneratorSourceName="Fill"??????????????? GetMethodModifier="Public"
GetMethodName="GetAllProducts" ?????????QueryType="Rowset"
ScalarCallRetval="System.Object, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
UseOptimisticConcurrency="False"
UserGetMethodName="GetAllProducts" UserSourceName="Fill">
?
?
??????? <DeleteCommand>
????????????????? <DbCommand CommandType="Text" ModifiedByUser="False">
???????? <CommandText>DELETE FROM [Products] WHERE (([ProductID] = @Original_ProductID))</CommandText>
??????????????????? <Parameters>
????????????????????? <Parameter AllowDbNull="False" AutogeneratedName="" DataSourceName="" DbType="Int32" Direction="Input" ParameterName="@Original_ProductID" Precision="0" ProviderType="Int" Scale="0" Size="0" SourceColumn="ProductID" SourceColumnNullMapping="False" SourceVersion="Original">
????????????????????? </Parameter>
??????????????????? </Parameters>
????????????????? </DbCommand>
??????????????? </DeleteCommand>
?
?
?????? <InsertCommand>
??? ??????????<DbCommand CommandType="Text" ModifiedByUser="False">
????????????? <CommandText>INSERT INTO [Products] ([ProductName], [CategoryID], [Price], [InStore], [Description]) VALUES (@ProductName, @CategoryID, @Price, @InStore, @Description)</CommandText>
??????????????????? <Parameters>
????????????????????? <Parameter AllowDbNull="True" AutogeneratedName="" DataSourceName="" DbType="String" Direction="Input" ParameterName="@ProductName" Precision="0" ProviderType="NVarChar" Scale="0" Size="0" SourceColumn="ProductName" SourceColumnNullMapping="False" SourceVersion="Current">
????????????????????? </Parameter>
????????????????????? <Parameter AllowDbNull="True" AutogeneratedName="" DataSourceName="" DbType="Int32" Direction="Input" ParameterName="@CategoryID" Precision="0" ProviderType="Int" Scale="0" Size="0" SourceColumn="CategoryID" SourceColumnNullMapping="False" SourceVersion="Current">
????????????????????? </Parameter>
????????????????????? <Parameter AllowDbNull="True" AutogeneratedName="" DataSourceName="" DbType="Currency" Direction="Input" ParameterName="@Price" Precision="0" ProviderType="Money" Scale="0" Size="0" SourceColumn="Price" SourceColumnNullMapping="False" SourceVersion="Current">
????????????????????? </Parameter>
????????????????? ????<Parameter AllowDbNull="True" AutogeneratedName="" DataSourceName="" DbType="Int16" Direction="Input" ParameterName="@InStore" Precision="0" ProviderType="SmallInt" Scale="0" Size="0" SourceColumn="InStore" SourceColumnNullMapping="False" SourceVersion="Current">
????????????????????? </Parameter>
????????????????????? <Parameter AllowDbNull="True" AutogeneratedName="" DataSourceName="" DbType="String" Direction="Input" ParameterName="@Description" Precision="0" ProviderType="NVarChar" Scale="0" Size="0" SourceColumn="Description" SourceColumnNullMapping="False" SourceVersion="Current">
????????????????????? </Parameter>
??????????????????? </Parameters>
????????????????? </DbCommand>
??????????????? </InsertCommand>
??????????????
?
?
?????? <SelectCommand>
????????????????? <DbCommand CommandType="Text" ModifiedByUser="True">
??????????????????? <CommandText>SELECT???? ProductID, ProductName, CategoryID, Price, InStore, Description
FROM???????? Products</CommandText>
??????????????????? <Parameters>
??? ????????????????</Parameters>
????????????????? </DbCommand>
??????????????? </SelectCommand>
?
?
?
??????????????? <UpdateCommand>
????????????????? <DbCommand CommandType="Text" ModifiedByUser="False">
??????????????????? <CommandText>UPDATE [Products] SET [ProductName] = @ProductName, [CategoryID] = @CategoryID, [Price] = @Price, [InStore] = @InStore, [Description] = @Description WHERE (([ProductID] = @Original_ProductID))</CommandText>
??????????????????? <Parameters>
????????????????????? <Parameter AllowDbNull="True" AutogeneratedName="" DataSourceName="" DbType="String" Direction="Input" ParameterName="@ProductName" Precision="0" ProviderType="NVarChar" Scale="0" Size="0" SourceColumn="ProductName" SourceColumnNullMapping="False" SourceVersion="Current">
????????????????????? </Parameter>
????????????????????? <Parameter AllowDbNull="True" AutogeneratedName="" DataSourceName="" DbType="Int32" Direction="Input" ParameterName="@CategoryID" Precision="0" ProviderType="Int" Scale="0" Size="0" SourceColumn="CategoryID" SourceColumnNullMapping="False" SourceVersion="Current">
????????????????????? </Parameter>
????????????????????? <Parameter AllowDbNull="True" AutogeneratedName="" DataSourceName="" DbType="Currency" Direction="Input" ParameterName="@Price" Precision="0" ProviderType="Money" Scale="0" Size="0" SourceColumn="Price" SourceColumnNullMapping="False" SourceVersion="Current">
????????????????????? </Parameter>
????????????????????? <Parameter AllowDbNull="True" AutogeneratedName="" DataSourceName="" DbType="Int16" Direction="Input" ParameterName="@InStore" Precision="0" ProviderType="SmallInt" Scale="0" Size="0" SourceColumn="InStore" SourceColumnNullMapping="False" SourceVersion="Current">
????????????????????? </Parameter>
????????????????????? <Parameter AllowDbNull="True" AutogeneratedName="" DataSourceName="" DbType="String" Direction="Input" ParameterName="@Description" Precision="0" ProviderType="NVarChar" Scale="0" Size="0" SourceColumn="Description" SourceColumnNullMapping="False" SourceVersion="Current">
????????????????????? </Parameter>
????????????????????? <Parameter AllowDbNull="False" AutogeneratedName="" DataSourceName="" DbType="Int32" Direction="Input" ParameterName="@Original_ProductID" Precision="0" ProviderType="Int" Scale="0" Size="0" SourceColumn="ProductID" SourceColumnNullMapping="False" SourceVersion="Original">
????????????????????? </Parameter>
??????????????????? </Parameters>
????????????????? </DbCommand>
??????????????? </UpdateCommand>
?
????????????? </DbSource>
??????????? </MainSource>
?
???????????? 代碼2-22 Database.xsd部分代碼(2)
?
3) 使用Mapping映射屬性
對于數據庫的列,系統使用Mapping元素將其映射為類的屬性,并設置其類型,如代碼2-23.
??????????? <Mappings>
????????????? <Mapping SourceColumn="ProductID" DataSetColumn="ProductID" />
????????????? <Mapping SourceColumn="ProductName" DataSetColumn="ProductName" />
????????????? <Mapping SourceColumn="CategoryID" DataSetColumn="CategoryID" />
????????????? <Mapping SourceColumn="Price" DataSetColumn="Price" />
????????????? <Mapping SourceColumn="InStore" DataSetColumn="InStore" />
????????????? <Mapping SourceColumn="Description" DataSetColumn="Description" />
??????????? </Mappings>
??????????? <Sources>
???????????? 代碼2-23 列和類屬性的映射
?
通過上面的處理,這樣我們就可以在代碼里用如下的方法定義數據適配器、數據表和數據行,
? DatabaseTableAdapters.ProductsTableAdapter pta =
?new DatabaseTableAdapters.ProductsTableAdapter();?
?Database.ProductsDataTable table? =? new Database.ProductsDataTable();
? Database.ProductsRow row?? =? new Database.ProductsRow()
在使用時請注意默認的命名方式:DatabaseTableAdapters映射整個適配器的命名空間,在該命名空間里包含多個數據適配表。
?
Simpe_DataAdapter.aspx演示了上面代碼的使用。代碼2-24是Simple_DataAdapter.aspx布局代碼
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Simple_DataAdapter.aspx.cs" Inherits="Simple_DataAdapter" %>
?
<html xmlns="http://www.w3.org/1999/xhtml" >
<body>
??? <form id="form1" runat="server">
??? <div>
??????? <asp:GridView ID="GridView1" runat="server" CellPadding="4" Font-Names="Verdana"
??????????? Font-Size="XX-Small" ForeColor="#333333" GridLines="None">
??????????? ... ...
??????? </asp:GridView>
???
??? </div>
??? </form>
</body>
</html>
?????? 代碼2-24 Simple_DataAdapter.aspx布局代碼
?
??? 代碼2-25是該頁面的后臺代碼。
public partial class Simple_DataAdapter : System.Web.UI.Page
{
??? protected void Page_Load(object sender, EventArgs e)
??? {
??????? DatabaseTableAdapters.ProductsTableAdapter pta = new DatabaseTableAdapters.ProductsTableAdapter();
??????? GridView1.DataSource = pta.GetAllProducts();
??????? GridView1.DataBind();
????? }
}
代碼2-25 Simple_DataAdapter.aspx.cs后臺代碼
代碼里的GetAllProducts來源與圖2-52里預定義的方法。圖2-52顯示了運行結果。從整個操作中,我們幾乎不用寫代碼,也不用設計到ADO.NET的細節就能夠完成數據庫里數據的讀取。
??????????????圖2-52 Simple_DataAdapter.aspx運行結果
這里僅僅演示了數據集和數據適配器的基本使用,事實上,用數據集和數據適配器能夠完成諸如 參數傳遞,存儲過程,等工作,如果你在設計數據庫時定義了表的關系,DataAdapter同樣能夠自動建立起映射關系。
查看。還是那句話,它用于DataAdapter顯示數據挺好,而執行諸如update,delete等工作,確實是吃力不討好的工作
如果你想知道DataAdapter的執行原理,也可以查看以前我發表的一篇文章
http://mqingqing123.cnblogs.com/archive/2005/10/11/252410.html
因為系統為你做的,就是自動化編譯
以上內容僅供參考,不保證正確性
總結
以上是生活随笔為你收集整理的数据访问模式二:数据集和数据适配器(传统的数据访问模式)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 鲶鱼精什么意思
- 下一篇: iPhone 究竟该不该贴膜,可能有哪些