導言
在上一章的教程中,我們看了GridView、DetailsView和FormView綁定到OjbectDataSource控制項顯示資料,ObjectDataSource調用了類ProductsBLL的GetProducts()方法。方法GetProducts()返回一個有Northwind資料庫的Products表的所有記錄組成的強型別資料表。類ProductsBLL還包含了其它返回部分資料的方法:GetProductByProductID(productID),GetProductsByCategoryID(categoryID), 和 GetProductsBySupplierID(supplierID) 。這三個方法要求輸入一個參數來指示如何篩選返回的產品資訊資料。
ObjectDataSource可以調用需要傳入參數的方法,不過為了實現這一點,我們需要指定這些參數從哪裡擷取值。這些參數的值可以通過硬代碼傳入,也可以從某類來源動態地擷取,包括:查詢字串的值(QueryString),會話變數(Session variables),頁面上控制項的屬性值,或者其它。
在這一章的教程裡,讓我們開始舉例說明如何使用參數設定一個硬式編碼值。特別地,我們將著眼於添加一個DetailsView到頁面來顯示一個名為Chef Anton's Gumbo Mix的特殊產品,它的ProductID是5 。下一步,我們將看看如何基於Web控制項設定參數的值。特別地,我們將使用一個TextBox讓使用者鍵入國家(country),在點擊某個按鈕後列出駐該國家的供應商。
使用一個寫入程式碼參數值
第一個例子,首先添加一DetailsView控制項到BasicReporting檔案夾裡的DeclarativeParams.aspx頁面。從DetailsView控制項的智能標記的下拉式清單中選擇<建立資料來源…>,然後選擇添加一個ObjectDataSource 。
圖 1: 添加一個ObjectDataSource到頁面
這將自動開啟ObjectDataSource控制項的配置資料來源導航。在第一屏的導航中選擇類ProductsBLL 。
圖 2: 選擇類ProductsBLL
既然我們要顯示一個特定的產品的資訊,我們應該使用GetProductByProductID(productID)方法。
圖 3: 選擇GetProductByProductID(productID) 方法
因為我們選擇了這個包含參數的方法,導航就多了一屏,在這一屏要求我們定義參數所用的值。在左邊的列表中顯示我們指定方法的所有參數。對於GetProductByProductID(productID)方法則只有一個參數:productID 。在右邊的參數源下拉式清單中列舉出有可能被作為參數源的幾類參數值。既然我們要指定一個硬式編碼值5用作productID參數,就讓參數源選項是None並在DefaultValue輸入框鍵入5 。
圖 4: 參數productID使用硬式編碼值
完成了設定資料來源精靈後,ObjectDataSource控制項的聲明標記裡就包含了一個SelectParameters集合,每一個SelectMethod屬性裡指定的方法的參數都對應一個Parameter對象。既然我們這個例子中的方法只要求一個參數parameterID ,那麼SelectParameters集合裡也就只有一個元素。SelectParameters集合可以包含任何來源於System.Web.UI.WebControls命名空間的類。因為是寫入程式碼參數值所以使用基本的Parameter類;如果需要的話你也可以建立自訂參數類型(custom parameter types)。
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="GetProductByProductID" TypeName="ProductsBLL"> <SelectParameters> <asp:Parameter DefaultValue="5" Name="productID" Type="Int32" /> </SelectParameters></asp:ObjectDataSource>
注意:如果你在自己的電腦上跟隨這些步驟聲明標記,你可能會看見這裡包含InsertMethod,UpdateMethod和 DeleteMethod 的參數值,比如DeleteParameters 。ObjectDataSource的選擇資料來源嚮導自動地指定了這些ProductBLL的方法從而實現插入、更新和刪除,因此,除非你明確地清除它們,否則它們將包含在上面的標記裡。
當訪問本頁面,Data Web伺服器控制項將調用ObjectDataSource的Select方法,這將調用類ProductsBLL的GetProductByProductID(productID),並使用“5”這個硬式編碼值作為輸入參數productID 。此方法將返回一個強型別的ProductDataTable對象,它包含一個資料行 - Chef Anton's Gumbo Mix的資訊(ProductID為5的產品)。
圖 5: 顯示Chef Anton's Gumbo Mix的相關資訊
設定Web控制項的屬性作為參數源
OjbectDataSource控制項的參數值也可以設定為基於頁面上的Web控制項的值。為了說明這一點,我們舉一個使用GridView來顯示位於使用者指定的國家的供應商的例子。首先,在頁面上添加一個TextBox控制項讓使用者輸入國家名稱。這個TextBox控制項的ID屬性設為CountryName 。再添加一個按鈕控制項到頁面。
圖 6: 添加一個ID為CountryName的TextBox控制項到頁面
Next, add a GridView to the page and, from the smart tag, choose to add a new ObjectDataSource. Since we want to display supplier information select the SuppliersBLL class from the wizard's first screen. From the second screen, pick the GetSuppliersByCountry(country) method.
然後,添加一個GridView控制項到頁面,從它的智能標記,選擇添加一個新的ObjectDataSource 。因為我們要顯示供應商資訊,所以在設定資料來源精靈第一屏選擇類SuppliersBLL 。第二屏,選擇GetSuppliersByCountry(country)方法。
圖 7: 選擇GetSuppliersByCountry(country) 方法
因為GetSuppliersByCountry(country)方法有一個輸入參數,所以嚮導再次顯示最後一屏,讓你選擇參數的值。這一次,設定參數源為Control,這時會出現一個ControlID下拉式清單,列表中包含頁面上所有控制項的名稱;從中選擇CountryName控制項。由於第一次訪問本頁面時文字框CountryName會為空白,那麼就沒有值從它返回,也就不顯示任何資料。如果你希望預設顯示一些結果,那麼要在DefaultValue文字框裡輸入一個預設的參數值。
圖 8: 設定CountryName控制項的值作為參數值
ObjectDataSource的聲明標記跟我們的第一個例子會稍有不同。使用一個 ControlParameter替代了標準的Parameter對象。ControlParameter具有一些額外的屬性用來指定Web控制項的ID,還有用作參數的屬性值(PropertyName)。設定資料來源精靈足以幫我們決定,例如TextBox,我們很有可能會使用它的Text屬性作為參數值。然而,如果你需要使用Web控制項的一個不同的屬性值,那麼你需要在這裡更改PropertyName屬性,或者從設定資料來源精靈裡點擊“進階屬性”。
<asp:ObjectDataSource ID="ObjectDataSource2" runat="server" SelectMethod="GetSuppliersByCountry" TypeName="SuppliersBLL"> <SelectParameters> <asp:ControlParameter ControlID="CountryName" Name="country" PropertyName="Text" Type="String" /> </SelectParameters></asp:ObjectDataSource>
當第一次訪問該頁面時,文字框CountryName裡的內容是空白的。GridView控制項仍然會調用ObjectDataSource的Select方法,但是,一個空值會被傳入GetSuppliersByCountry(country)方法。表適配器(TableAdapter)會將這個null值轉換成資料庫裡的NULL值(DBNull.Value),然而GetSuppliersByCountry(country)方法所使用的查詢已經寫明在傳入一個NULL值錯位參數@CategoryID時將不會返回任何結果。簡而言之,不會返回任何供應商。
一旦訪問正輸入一個國家,然後點擊Show Suppliers按鈕觸發一次回傳(postback),ObjectDataSource的Select方法被請求,同時傳遞文字框的Text值作為country參數。
圖 9: 顯示出位於Canada的供應商
預設顯示所有供應商
相對於在第一次訪問頁面時不顯示任何供應商,我們也許會希望一開始顯示所有的供應商,並且允許使用者通過在文字框裡輸入國家名稱來縮減列表。當文字框空白時,一個null值被傳遞到類SuppliersBLL的GetSuppliersByCountry(country)方法作為country輸入參數。這個null值繼續被傳遞到DAL層的GetSupplierByCountry(country)方法,在那裡它會被轉換成資料庫裡的NULL值用作下面這個查詢的@Country參數:
SELECT SupplierID, CompanyName, Address, City, Country, PhoneFROM SuppliersWHERE Country = @Country
運算式Country = NULL總是返回False,除非有某些記錄Country欄位的值恰好為NULL,否則不返回任何資料。
為了當文字框空白時返回所有的供應商,我們可以在BLL層的GetSuppliersByCountry(country)方法中加入:當參數country為null值時,調用GetSuppliers()方法而其他情況則調用DAL層的GetSuppliersByCountry(country)方法。這將實現以下的效果:當不指定國家時返回所有的國家,而當提供了country參數則返回適當的供應商子集。
更改類SuppliersBLL的GetSuppliersByCountry(country)方法,如下:
public Northwind.SuppliersDataTable GetSuppliersByCountry(string country){ if (string.IsNullOrEmpty(country)) return GetSuppliers(); else return Adapter.GetSuppliersByCountry(country);}
作了這個更改後,第一訪問頁面DeclarativeParams.aspx (或者當文字框CountryName空白時)將顯示所有的供應商。
圖 10: 現在,預設顯示所有供應商
總結
為了使用帶輸入參數的方法,我們需要在ObjectDataSource的SelectParameters集合裡指定參數的值。不同的參數類型允許從不同的參數源擷取它的值。預設的參數類型使用一個硬式編碼值,但是也可以非常方便地,從querystiring,Session變數,cookies,或者使用者從頁面上的Web控制項輸入的值擷取參數,甚者不需要寫一行的代碼。
這一章的教程了我們通過多個例子圖解了如何使用在資料來源中使用參數。然而,有些時候我們可能需要使用不可為空的參數,例如當前日期和時間,或者,如果我們的網站使用了Membership時訪問者的User ID 。這些情況我們可以通過編程預先設定ObjectDataSource調用的方法的參數值。在下一個章的教程裡,我們將看看如何?這一點。
祝編程快樂!
作者簡介
Scott Mitchell,著有六本ASP/ASP.NET方面的書,是4GuysFromRolla.com的創始人,自1998年以來一直應用微軟Web技術。Scott是個獨立的技 術諮詢顧問,培訓師,作家,最近完成了將由Sams出版社出版的新作,24小時內精通ASP.NET 2.0。他的聯絡電郵為mitchell@4guysfromrolla.com,也可以通過他的部落格http://ScottOnWriting.NET與他聯絡。