ASP.NET2.0中使用數據源控件之基礎知識
數據源控件是 Microsoft Visual Studio 2005 中引入的一種新型服務器控件,它們是數據綁定體系結構的一個關鍵部分,能夠通過數據綁定控件來提供聲明性編程模型和自動數據綁定行為。本文及此系列中的后續幾篇文章將介紹實現數據源控件的核心內容。
引言
簡而言之,數據源控件概括了一個數據存儲和可以針對所包含的數據執行的一些操作。DataBound 控件通過其 DataSourceID 屬性與一個數據源控件相關聯。大多數傳統的數據存儲要么是表格格式,要么是分層的,數據源控件也相應地分為兩類。在此要介紹的是表格格式的數據源控件。
數據源控件自身并不能發揮多大作用;所有邏輯都封裝在 DataSourceView 派生的類中。至少有一個 DataSourceView 必須實現檢索(即 SELECT)一組行的功能。它可以提供修改數據(即 INSERT、UPDATE 和 DELETE)的功能(可選)。數據綁定控件可通過各種 Can??? 屬性來檢查啟用功能集。數據源控件本身只是一個或多個唯一命名視圖的容器。依據慣例,默認視圖可以按其名稱進行訪問,也可以為空。不同視圖之間是否存在關系或者存在怎樣的關系可以根據每個數據源控件的實現情況來進行適當的定義。例如,某個數據源控件可能會通過不同的視圖對同一個數據提供不同的經篩選的視圖,或者可能會在輔助視圖中提供一組子行。可使用數據綁定控件的 DataMember 屬性來選擇某個特殊的視圖(如果該數據源控件提供了多個視圖)。請注意,Whidbey 中的所有內置數據源控件目前都不提供多個視圖。
最后再介紹一點內容。數據源控件(及其視圖)會實現兩組 API。第一組 API 是就四種常用的數據操作而定義的一個抽象界面,以常規方式從任一數據綁定控件中使用。第二組是可選的,它使用其表示的域或數據存儲方面的術語來定義,通常被強類型化,且面向應用程序開發人員。
示例
在這些文章中,將實現一個 WeatherDataSource,它將針對由 weather.com(英文)提供的 REST(英文)XML API 來工作,以便根據郵政編碼來檢索天氣信息。通常會首先實現派生的數據源控件。
如您所見,基本的理念是實現 GetView 以返回一個命名視圖實例,以及實現 GetViewNames 以返回可用視圖集。
在此選擇從 DataSourceControl 中派生。有一點是不易察覺的,事實上數據綁定控件要查找 IDataSource 界面,而 DataSource 控件通過實現 GetView 和 GetViewNames 來實現該界面。之所以需要界面是為了使數據源控件能夠既是表格格式又是分層的(如果可能的話),在這種情況下從主要模型中派生并將另一個模型作為界面來實現)。其次,還允許在各種方案中轉換其他控件,以使數據源的容量加倍。 另外還要注意公共 ZipCode 屬性和返回強類型化 Weather 對象的 GetWeather 方法。此 API 適合于頁面開發人員。頁面開發人員無需考慮 DataSourceControl 和 DataSourceView。
下一步是實現數據源視圖本身。此特定示例僅提供了 SELECT 級功能(這只是最低要求,也是在此方案中唯一有用的功能)。
默認情況下,DataSourceView 類從諸如 CanUpdate 等的屬性返回 false,而從 Update 和相關方法拋出 NotSupportedException。在此,在 WeatherDataSourceView 中唯一需要做的就是替代抽象的 ExecuteSelect 方法,返回包含“選定”天氣數據的 IEnumerable。在實現過程中,使用了幫助程序 WeatherService 類,該類僅使用 WebRequest 對象來查詢 weather.com(英文),方法是使用所選的郵政編碼(這沒什么特別的)。
您可能注意到了,ExecuteSelect 被標記為受保護。數據綁定控件實際調用的是在回撥中傳遞的公共(和密封)Select 方法。Select 的實現會調用 ExecuteSelect,并調用回撥與得到的 IEnumerable 實例。這種模式非常古怪。這其中有一個原因,此系列隨后的文章中將會加以說明。請稍候...
下面是該用法的示例:
此代碼設置了郵政編碼來響應用戶輸入,這會使數據源發出更改通知,從而使綁定的 FormView 控件執行數據綁定并更改顯示。
現在,數據訪問代碼就被封裝在數據源控件中。此外,通過此模型,weather.com(英文)能夠發布一個組件,該組件還可以封裝特定于其服務的詳細信息。但愿它會好用。此外,抽象的數據源界面允許 FormView 僅針對天氣數據進行工作。
在下一篇文章中,將增強數據源控件的功能,使其能夠自動處理用來查詢數據的篩選值(即郵政編碼)的更改。
引言
簡而言之,數據源控件概括了一個數據存儲和可以針對所包含的數據執行的一些操作。DataBound 控件通過其 DataSourceID 屬性與一個數據源控件相關聯。大多數傳統的數據存儲要么是表格格式,要么是分層的,數據源控件也相應地分為兩類。在此要介紹的是表格格式的數據源控件。
數據源控件自身并不能發揮多大作用;所有邏輯都封裝在 DataSourceView 派生的類中。至少有一個 DataSourceView 必須實現檢索(即 SELECT)一組行的功能。它可以提供修改數據(即 INSERT、UPDATE 和 DELETE)的功能(可選)。數據綁定控件可通過各種 Can??? 屬性來檢查啟用功能集。數據源控件本身只是一個或多個唯一命名視圖的容器。依據慣例,默認視圖可以按其名稱進行訪問,也可以為空。不同視圖之間是否存在關系或者存在怎樣的關系可以根據每個數據源控件的實現情況來進行適當的定義。例如,某個數據源控件可能會通過不同的視圖對同一個數據提供不同的經篩選的視圖,或者可能會在輔助視圖中提供一組子行。可使用數據綁定控件的 DataMember 屬性來選擇某個特殊的視圖(如果該數據源控件提供了多個視圖)。請注意,Whidbey 中的所有內置數據源控件目前都不提供多個視圖。
最后再介紹一點內容。數據源控件(及其視圖)會實現兩組 API。第一組 API 是就四種常用的數據操作而定義的一個抽象界面,以常規方式從任一數據綁定控件中使用。第二組是可選的,它使用其表示的域或數據存儲方面的術語來定義,通常被強類型化,且面向應用程序開發人員。
示例
在這些文章中,將實現一個 WeatherDataSource,它將針對由 weather.com(英文)提供的 REST(英文)XML API 來工作,以便根據郵政編碼來檢索天氣信息。通常會首先實現派生的數據源控件。
public class WeatherDataSource : DataSourceControl { public static readonly string CurrentConditionsViewName = "CurrentConditions"; private WeatherDataSourceView _currentConditionsView; private WeatherDataSourceView CurrentConditionsView { get { if (_currentConditionsView == null) { _currentConditionsView = new WeatherDataSourceView(this, CurrentConditionsViewName); } return _currentConditionsView; } } public string ZipCode { get { string s = (string)ViewState["ZipCode"]; return (s != null) ? s : String.Empty; } set { if (String.Compare(value, ZipCode, StringComparison.Ordinal) != 0) { ViewState["ZipCode"] = value; CurrentConditionsView.RaiseChangedEvent(); } } } protected override DataSourceView GetView(string viewName) { if (String.IsNullOrEmpty(viewName) || (String.Compare(viewName, CurrentConditionsViewName, StringComparison.OrdinalIgnoreCase) == 0)) { return CurrentConditionsView; } throw new ArgumentOutOfRangeException("viewName"); } protected override ICollection GetViewNames() { return new string[] { CurrentConditionsViewName }; } public Weather GetWeather() { return CurrentConditionView.GetWeather(); } } |
如您所見,基本的理念是實現 GetView 以返回一個命名視圖實例,以及實現 GetViewNames 以返回可用視圖集。
在此選擇從 DataSourceControl 中派生。有一點是不易察覺的,事實上數據綁定控件要查找 IDataSource 界面,而 DataSource 控件通過實現 GetView 和 GetViewNames 來實現該界面。之所以需要界面是為了使數據源控件能夠既是表格格式又是分層的(如果可能的話),在這種情況下從主要模型中派生并將另一個模型作為界面來實現)。其次,還允許在各種方案中轉換其他控件,以使數據源的容量加倍。 另外還要注意公共 ZipCode 屬性和返回強類型化 Weather 對象的 GetWeather 方法。此 API 適合于頁面開發人員。頁面開發人員無需考慮 DataSourceControl 和 DataSourceView。
下一步是實現數據源視圖本身。此特定示例僅提供了 SELECT 級功能(這只是最低要求,也是在此方案中唯一有用的功能)。
private sealed class WeatherDataSourceView : DataSourceView { private WeatherDataSource _owner; public WeatherDataSourceView(WeatherDataSource owner, string viewName) : base(owner, viewName) { _owner = owner; } protected override IEnumerable ExecuteSelect( DataSourceSelectArguments arguments) { arguments.RaiseUnsupportedCapabilitiesError(this); Weather weatherObject = GetWeather(); return new Weather[] { weatherObject }; } internal Weather GetWeather() { string zipCode = _owner.ZipCode; if (zipCode.Length == 0) { throw new InvalidOperationException(); } WeatherService weatherService = new WeatherService(zipCode); return weatherService.GetWeather(); } internal void RaiseChangedEvent() { OnDataSourceViewChanged(EventArgs.Empty); } } |
默認情況下,DataSourceView 類從諸如 CanUpdate 等的屬性返回 false,而從 Update 和相關方法拋出 NotSupportedException。在此,在 WeatherDataSourceView 中唯一需要做的就是替代抽象的 ExecuteSelect 方法,返回包含“選定”天氣數據的 IEnumerable。在實現過程中,使用了幫助程序 WeatherService 類,該類僅使用 WebRequest 對象來查詢 weather.com(英文),方法是使用所選的郵政編碼(這沒什么特別的)。
您可能注意到了,ExecuteSelect 被標記為受保護。數據綁定控件實際調用的是在回撥中傳遞的公共(和密封)Select 方法。Select 的實現會調用 ExecuteSelect,并調用回撥與得到的 IEnumerable 實例。這種模式非常古怪。這其中有一個原因,此系列隨后的文章中將會加以說明。請稍候...
下面是該用法的示例:
Zip Code: <asp:TextBox runat="server" id="zipCodeTextBox" /> <asp:Button runat="server" onclick="OnLookupButtonClick" Text="查找" /> <hr /> <asp:FormView runat="server" DataSourceID="weatherDS"> <ItemTemplate> <asp:Label runat="server" Text='<%# Eval("Temperature", "當前溫度是 {0}。") %>' /> </ItemTemplate> </asp:FormView> <nk:WeatherDataSource runat="server" id="weatherDS" ZipCode="98052" /> <script runat="server"> private void OnLookupButtonClick(object sender, EventArgs e) { weatherDS.ZipCode = zipCodeTextBox.Text.Trim(); } </script> |
此代碼設置了郵政編碼來響應用戶輸入,這會使數據源發出更改通知,從而使綁定的 FormView 控件執行數據綁定并更改顯示。
現在,數據訪問代碼就被封裝在數據源控件中。此外,通過此模型,weather.com(英文)能夠發布一個組件,該組件還可以封裝特定于其服務的詳細信息。但愿它會好用。此外,抽象的數據源界面允許 FormView 僅針對天氣數據進行工作。
在下一篇文章中,將增強數據源控件的功能,使其能夠自動處理用來查詢數據的篩選值(即郵政編碼)的更改。