摘要 本文試圖對Visual Studio
自動生成的數據存取層(DAL)作深入分析
最終達到在此基礎上進一步編輯和擴展此代碼之目的
一 引言 Visual Studio
提出了
用更少的代價實現更高的性能
的口號
Visual Studio
中提供了大量的向導—特別是在生成數據存取代碼方面
這些向導大大減少了代碼的編寫量
請注意
自動添加到你的工程中的任何代碼都遵循了某種嚴格的邏輯和良好的設計模式
因此
全面理解Visual Studio
在這方面的工作原理有助於你以後進一步修改和擴展這些代碼從而構建你自己的定制的數據存取層
本文將對表格適配器和綁定源組件相應的代碼展開深入的分析
自從微軟發行
NET框架
Visual Studio
和ASP
NET
以來
其關鍵賣點之一在於
同樣的工作如今你只需要編寫更少的代碼
並且常常不需要任何編碼
簡言之
no
code
at
all
的口號其實是大量存在的向導
插件與設計器—你可以通過鼠標拖動
復選框和按鈕交互方式在其中進行編程
只要對你想實現的內容加以
聲明
那麼微軟的工具會針對你提出的要求生成相應的代碼
你可能還記得那名老口號
所見即所得
—正是在這種口號倡導下產生了如Visual Basic這樣的快速原型開發工具
我想
現在我們可以把這個口號再改一下
那就是
所得即工具所想
(what
you
get
is
what
the
tool
thinks
you
want)
事實上
在Visual Studio
中
你會發現存在大量的Windows表單和ASP
NET數據控件用於連接到中間層對象以便迅速而高效地創建數據驅動的應用程序
基於最新的Visual Studio
數據設計器
你可以通過用戶驅動的向導來創建代碼
然而
在你點擊
Finish
按鈕後得到的代碼中往往包含了比以前版本的Visual Studio中更多的抽象
在此基礎上
雖然你只需使用例如表格適配器和類型化的數據集等頂層對象
但是你最終得到的卻是一個
瘦
的更好的中間層
而且
更重要的是
你可以選擇把這個頂層API連接到你自己的數據存取層
從而完成一個正規化多層系統
我的建議是
在任何情況下
你都應該避免把大量的ADO
NET相關的表單代碼插入到ASP
NET頁面和Windows表單事件的code
behind中
你應該總是堅持使用分層設計
並使用數據傳輸模式和有效的數據描述方式
但是
Visual Studio能夠提供數據集並自動生成ADO
NET代碼
另外
如今的Visual Studio
還能夠為你提供數據集和定制對象並能自動生成一個能夠進行大幅度定制的抽象層
在本文中
我將從面向對象設計的角度來分析和討論Visual Studio
數據設計器生成的代碼
二 構建一個數據驅動的Windows表單 讓我們一步步來創建一個數據驅動的Windows表單應用程序
我們的總體想法是構建一個基於表單的應用程序
它能夠顯示並編輯來自於Northwind數據庫多個表格的數據
圖
顯示了最終的應用程序運行情況
圖
本文示例程序的最終顯示結果
這個表單上有一些數據綁定控件
還有幾個數據連接器控件
典型情況下
你首先要添加BindingNavigator控件以便讓用戶在一個綁定數據源記錄中進行導航
這個BindingNavigator控件有一個類似於VCR的用戶接口
它僅負責從數據源選擇一個特定的記錄並使之可應用於一個通用的編程接口
這個BindingNavigator控件提供的用戶接口很容易使人聯想到Microsoft Access中的工具欄
在Windows Form
中
大多數控件不直接綁定到一個集合對象
而是使用一個中間對象—綁定源—該綁定源被綁定到一個典型的可枚舉的數據源對象上
注意
這個BindingNavigator控件不會拋出任何異常
綁定源組件的設計目的主要是為了簡化表單上的控件和綁定數據之間的綁定
另外
它還提供了許多其它類型的服務(如當前狀態管理
改變通知
過濾等)
如前面所提及
一個綁定源組件其實是在用戶接口元素和後端數據之間添加了一個間接層
如圖
所示
圖
綁定源組件介於用戶接口和數據源之間
你需要把該綁定源組件連接到一個物理數據源然後把表單上的控件綁定到該綁定源從現在開始任何與數據源相關的數據交互都是通過這個綁定源實現的典型的操作包括導航檢索排序過濾和更新
其實NET框架中的一個綁定源組件是一個派生自類BindingSource的類的實例注意盡管這個術語比較新一些並且特定於NET框架但是綁定源組件背後的核心概念對於一位NET Windows開發老手來說應該不陌生
是的這種綁定源組件其實就是一個沒有用戶界面的組件專門設計用於讓開發者從Visual Studio 內部管理綁定對象並且多數是以聲明方式實現的
三 BindingSource類
BindingSource類負責包裝一個數據源並通過它自己的對象模型來暴露該數據源表格列出了BindingSource基類的主要屬性
表格BindingSource類的編程接口
屬性
描述
AllowEdit
指示是否能夠編輯在底層數據源中的項
AllowNew
指示是否該新項能夠被添加到底層數據源
AllowRemove
指示是否能夠從底層數據源中刪除這些項
Count
從底層數據源中取得的項的數目
CurrencyManager
取得一個對相關聯的當前狀態管理器的引用
Current
取得底層數據源中的當前項
DataMember
指示數據源中的一個特定的列表
DataSource
指示連接器綁定的數據源
Filter
用於過濾數據源的表達式
IsReadOnly
指示是否底層數據源是只讀的
IsSorted
指示是否底層數據源中的該項已經被排序
Item
檢索相應於指定索引的數據源項
List
取得連接器被綁定到的列表
Position
指示底層數據源中當前項的索引
Sort
指示用於排序的列名以及排序的順序
SortDirection
指示在數據源中排序項的方法
SortProperty
取得用於排序數據源的PropertyDescriptor對象
SupportsAdvancedSorting
指示是否數據源支持多欄排序
SupportsChangeNotification
指示是否數據源支持改變通知
SupportsFiltering
指示是否數據源支持過濾
SupportsSearching
指示是否數據源支持搜索
SupportsSorting
指示是否數據源支持排序
值得注意的是BindingSource對象的設計目的是既用來管理簡單的數據綁定也應用於復雜的數據綁定場所—這意味著它合並了NET框架x中CurrencyManager和PropertyManager的所有功能基於此我們應該注意到表格中的基本數據源經常指一個集合(例如一個類型化的數據集)但也可以是單個的對象(例如一個獨立的DataRow)
從表格中的屬性可見綁定源組件擁有一個Position成員它用於指示當前選擇的數據項的索引該BindingSource類並沒有提供任何用戶接口因此這裡所謂的選擇純粹是從邏輯上講的由綁定控件負責把邏輯選擇轉換成對用戶可見而且有意義的一些內容Current屬性指向在當前選擇位置檢索到的數據該BindingSource類還暴露一些方法用於實現前後移動選擇內容或跳轉到一個特定的位置還有一個事件用於指示當前選擇的元素已經發生改變
為了實現這些功能並且使它們快速而容易地出現在用戶接口級你可以使用BindingNavigator控件並且把它關聯到一個綁定源上每當用戶點擊圖中類似於VCR的按鈕綁定源上的Position和Current屬性被更新並且激發CurrentChanged事件就象在WindowsForms x時期的數據綁定一樣監聽這些事件的控件接收通知並且能夠適當更新各自的用戶接口下面讓我們繼續討論Visual Studio 中數據源的定義問題
四 把數據源導入Windows表單應用程序
為了把數據添加到你的Windows應用程序你首先要把一個BindingSource組件拖動到你的表單然後你要設置該組件的DataSource屬性存在許多可用的數據源包括數組集合和定制類型列表典型情況下列表都是在集合的基礎上擴展而成的它們要實現下列任何接口IBindingListITypedList或IListSource注意流行的ADONET容器類例如DataSet和DataTable都屬於最後一種類型因為它們都實現了IListSource接口
在最開始你的應用程序沒有數據源—你必須要為之創建一個當你選擇BindingSource組件的DataSource屬性時你會遇到一個類似於圖所示的窗口點擊彈出窗口底部的鏈接從而啟動一個向導以便把一個新的數據源添加到當前工程
圖在工程上添加一個新的數據源
此向導中Visual Studio 會非常禮貌地詢問應用程序想從哪裡得到數據存在三個可能的場所數據庫外部Web服務或定制對象如果你選擇了Web服務那麼Visual Studio 將打開Add Web Reference對話框以便讓你選擇使用一個本地的還是遠程的Web服務並且創建相應的代理類然後將由你來檢索數據並且把它綁定到控件同樣你可以從工程引用的任何程序集內選擇一個定制對象
定制對象集合或Web服務的創作者負責設計並且使用他們喜歡的任何方法來實現對象模型當你選擇該數據庫選項時Visual Studio 會為你生成大量的代碼典型地你需要添加一個DataSet組件也即是通過一個XSD文件描述的一組相互關聯的表格這個DataSet組件描述了一個具有一個或多個數據表格的內存DataSet對象注意到目前為此Visual Studio 的行為與Visual Studio沒有什麼很大的不同—類型化的數據集類都是由聲明性XSD文件創建的
五 表格適配器(TableAdapter)
一個表格適配器為一個應用程序與它的數據庫之間的通信提供支持例如一個表格適配器連接到一個數據庫並且執行命令任何返回的數據被存儲到一個DataTable對象中以備進一步處理你還能夠使用一個表格適配器來把更新內容發送回數據庫其實一個表格適配器是一個工具生成的類的實例一個表格適配器只是在NET托管的提供程序內定義的適配器類的一個特例簡言之它是一個擔當針對特定表格的適配器的包裝器對象注意表格適配器沒有基類
下面的代碼片斷展示了一個表格適配器類典型的定義形式
Partial Public Class CustomersTableAdapter
Inherits SystemComponentModelComponent
End Class
從內部實現來看一個表格適配器類合並了一個SqlCommandSqlConnection和SqlDataAdapter對象的功能在Visual BasicNET中數據適配器使用了WithEvents修飾詞以便捕獲事件表格列舉了一個表格適配器的內部屬性
表格一個表格適配器類的內部成員
成員
修飾詞
描述
Adapter Private
ReadOnly
用於與相應的數據庫表格進行通訊的數據適配器
Connection
Friend
用於與相應的數據庫表格進行通訊的連接對象
CommandCollection Protected
ReadOnly
定義了一組描述表格適配器行為的命令對象為了增強可以通過表格適配器實現的任務你可以把一個新的命令添加到這個集合
ClearBeforeFill
Public
指示是否表格在填充之前應該為空默認情況下為True
內部數據適配器是在InitAdapter方法中初始化的該方法是從Adapter屬性的get存取器內進行調用的
Private ReadOnly Property Adapter() _
As SystemDataSqlClientSqlDataAdapter
Get
If (Me_adapter Is Nothing) Then
MeInitAdapter
End If
Return Me_adapter
End Get
End Property
在此適配器是一個助理對象用於驅動在底層表格上的標准的CRUD(創建讀取更新刪除)操作這個適配器負責定義相應於InsertDelete和Update命令的缺省TSQL語句它並沒有包括一個Select命令由於主要是為了便於使用數據填充數據表格所以適配器通過在表格適配器中的一對public類型方法(分別為Fill和GetData)實現了它的Select功能
任何數據操作都要求建立到數據源的一個物理連接相應源碼中的列表展示了Connection屬性的內部實現這個Connection字符串存儲在應用程序的配置文件內可以在任何時候預以編輯而無需修改和重新編譯基本代碼當你建立一個新的連接時該信息被自動地傳遞到表格適配器中所有的命令對象
後面你會看到表格適配器類是用於實現數據存取的流行設計模式中的非常重要的元素之一借助於CommandCollection屬性表格適配器類能夠列出在表格上執行的所有行為簡言之它定義了表格的行為
Protected ReadOnly Property CommandCollection() _
As SystemDataSqlClientSqlCommand()
Get
If (Me_commandCollection Is Nothing) Then
MeInitCommandCollection
End If
Return Me_commandCollection
End Get
End Property
默認情況下該CommandCollection僅包含一個命令—實現Select操作的TSQL命令下列代碼展示了對這個集合的初始化
Private Sub InitCommandCollection()
_commandCollection = New SqlCommand() {}
_commandCollection() = New SqlCommand
_commandCollection()Connection = MeConnection
_commandCollection()CommandText = SELECT * FROM Customers
_commandCollection()CommandType = CommandTypeText
End Sub
這個集合內的缺省命令對象被包裝在Fill和GetData方法內(見源碼中的列表)其中Fill負責使用命令結果填充數據表格而GetData能夠使用相同的數據返回一個新的DataTable對象表格列出了該表格適配器類的所有public方法
表格一個表格適配器類提供的方法
方法
描述
Fill
使用執行命令集合中的缺省命令所返回的結果來填充與這個表格適配器相關聯的數據表格
GetData
返回一個新創建的DataTable對象其中填充有執行命令集合中的缺省命令取得的數據
Delete
執行與內部數據適配器相關聯的DELETE命令
Insert
執行與內部數據適配器相關聯的INSERT命令
Update
執行與內部數據適配器相關聯的UPDATE命令這個方法提供若干重載形式
From:http://tw.wingwit.com/Article/program/net/201311/11974.html