Stephen Walther
Superexpert
適用于:
Microsoft ASP.NET 2.0
Microsoft Visual Studio 2005
摘要:ADO.NET 和 SqlDataSource 使得人們可以很容易地訪問 ASP.NET 2.0 中的兩層數據。但是,它們在 n 層應用程序中就不是那么有效了,而 ObjectDataSource 卻能在 n 層應用程序中為業務對象提供相同的易用性。學習如何使用 ASP.NET 2.0 Framework 并利用 ObjectDataSource 控件生成嚴格意義上的多層 Web 應用程序。
本頁內容
簡介 | |
使用 ObjectDataSource 控件顯示數據 | |
結合使用參數與 ObjectDataSource 控件 | |
使用 ObjectDataSource 控件編輯數據 | |
結合使用 ObjectDataSource 控件和 SqlDataSource 控件 | |
小結 |
簡介
在 Microsoft ASP.NET 2.0 Framework 中,數據庫訪問得到了極大的簡化。利用全新的 SqlDataSource 控件,您無需編寫一行代碼就可以選擇、更新、插入和刪除數據庫數據。
生成簡單的應用程序時,SqlDataSource 控件是一個很好的選擇。如果您需要迅速生成一個使用戶可以顯示和編輯數據庫記錄的 Web 頁,使用 SqlDataSource 控件在幾分鐘之內就能完成此工作。
例如,我自己就曾計時生成了這么一個頁面。通過結合使用 SqlDataSource 控件與 GridView 控件,我在 1 分 15秒 內就能生成一個用于顯示 Northwind Products 數據庫表的內容的頁面。就有這么快!
但是,SqlDataSource 控件存在一個問題。如果您使用 SqlDataSource 控件,那您就是在做不太妙的事情。SqlDataSource 控件的缺點在于它迫使您將用戶界面層與業務邏輯層混合在一起。任何應用程序架構師都會告訴您:混合多個層的行為是不可取的。
生成嚴格意義上的多層 Web 應用程序時,您應該具有清晰的用戶界面層、業務邏輯層和數據訪問層。僅僅由于 SqlDataSource 控件的強制而在用戶界面層引用 SQL 語句或存儲過程是完全錯誤的。
那么為什么您要關心這些東西呢?不錯,在很多情況下,您不必在意。如果您正在創建一個簡單的 Web 應用程序,完全可以使用 SqlDataSource 控件。例如,如果您需要生成一個由單獨頁面組成的應用程序來顯示數據庫的表的內容,那么將應用程序劃分為多個應用程序層就很不明智。
遺憾的是(如果您已經為此“交過學費”,則會感到幸運),并非所有的 Web 應用程序都很簡單。應用程序達到一定的復雜程度之后,如果將其劃分為多個應用程序層,則生成和維護它們就更輕松。
將應用程序劃分為多個應用程序層有很多優點。如果您有一個清晰的業務邏輯層,就能夠創建一個可以從多個頁面調用的方法庫。換句話說,創建一個清晰的業務邏輯層提升了代碼重用。此外,創建清晰而獨立的應用程序層使得應用程序更易于修改。例如,清晰的層次使您無需修改數據訪問代碼就可以修改用戶界面。
如果您需要使用 ASP.NET Framework 生成多層 Web 應用程序,那么您可以使用 ASP.NET 2.0 Framework 所引入的另一個新控件:ObjectDataSource 控件ObjectDataSource 控件使您可將諸如 GridView 和 DropDownList 這樣的用戶界面控件綁定到一個中間層組件。
這篇文章的主題就是 ObjectDataSource 控件。在這篇文章中,您將學習如何使用此控件來顯示和編輯數據庫數據。我們還將討論如何結合使用 ObjectDataSource 控件和 SqlDataSource 控件以簡化數據庫訪問。
使用 ObjectDataSource 控件顯示數據
我們在這里設想您需要創建一個用于顯示 Products 數據庫表的內容的 Web 頁面。再進一步設想您的某個現有業務組件包含了一種用于檢索此數據的方法。
例如,清單 1 中的組件包含了一個名為 GetProducts 的方法,此方法返回一個 DataReader 來表示 Products 數據庫表的內容。
清單 1: ProductInfo.cs (C#)
using System; using System.Data; using System.Data.SqlClient; public class ProductInfo { const string conString = "Server=localhost;Trusted_Connection=true;Database=Northwind"; public static SqlDataReader GetProducts() { SqlConnection con = new SqlConnection(conString); string selectString = "SELECT * FROM Products"; SqlCommand cmd = new SqlCommand(selectString, con); con.Open(); SqlDataReader dtr = cmd.ExecuteReader(CommandBehavior.CloseConnection); return dtr; } }
如果您將清單 1 中包含的這個類添加到應用程序的 Code 目錄中,那么 ASP.NET Framework 將自動編譯這個類。換句話說,只要向 Code 目錄添加了這個類,就可以立即在 ASP.NET 頁中使用它。
我們將使用 GridView 控件(在 ASP.NET 2.0 Framework 中替換了 DataGrid 控件)來顯示由 GetProducts 方法返回的數據庫記錄。清單 2 中的 ASP.NET 頁包含了一個綁定到 ObjectDataSource 控件的 GridView。
清單 2: ShowProducts.aspx
<html> <head> <title>Show Products</title> </head> <body> <form id="form1" runat="server"> <asp:GridView ID="GridView1" DataSourceID="ObjectDataSource1" Runat="Server" /> <asp:ObjectDataSource ID="ObjectDataSource1" TypeName="ProductInfo" SelectMethod="GetProducts" Runat="Server" /> </form> </body> </html>
清單 2 中聲明的 ObjectDataSource 控件包含兩個重要的屬性。TypeName 屬性指示類名,而 SelectMethod 屬性指示在選擇數據時要在此類上調用的方法名。
在清單 2 中,ObjectDataSource 控件用于調用 ProductInfo 類上的 GetProducts 方法。由于 GridView 控件綁定到了 ObjectDataSource 控件上,因此通過 GridView 控件的 DataSourceID 屬性,GridView 控件即可顯示產品列表(請參見圖 1)。
圖 1. 使用 ObjectDataSource 控件顯示產品
您可以結合使用 ObjectDataSource 控件與任何標準的 ASP.NET 數據綁定控件(例如,GridView、DropDownList、TreeView 和 Repeater 控件)。ObjectDataSource 控件使您能夠將任何標準控件綁定到組件。
SelectMethod 可以引用靜態方法(在 Visual Basic .NET 中共享)或實例方法。如果您使用的是實例方法,則 ObjectDataSource 控件在調用這個方法前,會自動創建此組件的一個實例。在完成方法調用后,將自動銷毀此組件。
結合使用參數與 ObjectDataSource 控件
您可以將參數與使用 ObjectDataSource 控件調用的方法一起使用。當您調用某方法時,如果需要將某些值(例如,控件屬性或查詢字符串的值)傳遞給此方法,則這種方式就非常有用。
在前一節中,我們使用 ObjectDataSource 控件創建了一個頁面,用于顯示來自 Products 數據庫表的所有記錄。在本節中,我們將修改此頁面,以便允許用戶從 DropDownList 控件(請參見圖 2)選擇產品類別。
圖 2. 從 DropDownList 選擇產品類別
清單 3 包含了修改后的 ProductInfo 組件。
清單 3: ProductInfo2.cs (C#)
using System; using System.Data; using System.Data.SqlClient; public class ProductInfo2 { const string conString = "Server=localhost;Trusted_Connection=true;Database=Northwind"; public SqlDataReader GetProducts(string category) { SqlConnection con = new SqlConnection(conString); string selectString = "SELECT Products.* " + "FROM Products INNER JOIN Categories " + "ON Products.CategoryID=Categories.CategoryId " + "WHERE CategoryName=@CategoryName"; SqlCommand cmd = new SqlCommand(selectString, con); cmd.Parameters.AddWithValue("@CategoryName", category); con.Open(); SqlDataReader dtr = cmd.ExecuteReader(CommandBehavior.CloseConnection); return dtr; } }
清單 3 中經過修改的 ProductInfo 組件包含了一個經過修改的 GetProducts 方法,此方法包含了一個用于類別名的參數。這個參數用于限制從數據庫返回的產品。
清單 4 包含了 DropDownList、GridView 和ObjectDataSource 控件,使您可以選擇要顯示的不同類別的產品。
清單 4: ShowProducts2.aspx
<html> <head> <title>Show Products</title> </head> <body> <form id="form1" runat="server"> <asp:DropDownList id="DropCategories" AutoPostBack="true" Runat="Server"> <asp:ListItem Value="Beverages" /> <asp:ListItem Value="Seafood" /> </asp:DropDownList> <br /><br /> <asp:GridView ID="GridView1" DataSourceID="ObjectDataSource1" Runat="Server" /> <asp:ObjectDataSource ID="ObjectDataSource1" TypeName="ProductInfo2" SelectMethod="GetProducts" Runat="Server"> <SelectParameters> <asp:ControlParameter Name="category" ControlID="DropCategories" /> </SelectParameters> </asp:ObjectDataSource> </form> </body> </html>
從清單 4 的 DropDownList 控件選擇新類別時,GridView 控件將自動地只顯示來自選定類別的產品。
請注意,清單 4 中的 ObjectDataSource 控件包含了一個 SelectParameters 元素。這個元素列出了調用由 ObjectDataSource 控件的 SelectMethod 屬性指定的方法時使用的所有參數。在本例中,SelectedParameters 元素包含了一個名為 category 的單個參數。這個參數表示來自 DropCategoriesDropDownList 控件的 SelectedValue 屬性的值。
使用 ObjectDataSource 控件編輯數據
ObjectDataSource 控件包含 4 個重要屬性:SelectMethod 屬性、UpdateMethod 屬性、InsertMethod 屬性和 DeleteMethod 屬性。綜合利用這些屬性,您能夠指定執行標準數據庫操作所需的所有方法。
例如,您可以使用 ObjectDataSource 控件來編輯數據庫數據。在清單 5 中,修改后的 ProductInfo 類包含了一個新的 UpdateProduct 和 DeleteProduct 方法。
清單 5: ProductInfo3.cs (C#)
using System; using System.Data; using System.Data.SqlClient; public class ProductInfo3 { const string conString = "Server=localhost;Trusted_Connection=true;Database=Northwind"; public static SqlDataReader GetProducts() { SqlConnection con = new SqlConnection(conString); string selectString = "SELECT ProductId,ProductName, " + "UnitPrice FROM Products ORDER BY ProductId"; SqlCommand cmd = new SqlCommand(selectString, con); con.Open(); SqlDataReader dtr = cmd.ExecuteReader(CommandBehavior.CloseConnection); return dtr; } public static void UpdateProduct(int original_productId, string productName, decimal unitPrice) { SqlConnection con = new SqlConnection(conString); string updateString = "UPDATE Products SET " + "ProductName=@ProductName,UnitPrice=@UnitPrice " + "WHERE ProductID=@ProductID"; SqlCommand cmd = new SqlCommand(updateString, con); cmd.Parameters.AddWithValue("@ProductName", productName); cmd.Parameters.AddWithValue("@UnitPrice", unitPrice); cmd.Parameters.AddWithValue("@ProductId", original_productId); con.Open(); cmd.ExecuteNonQuery(); con.Close(); } public static void DeleteProduct(int original_productId) { SqlConnection con = new SqlConnection(conString); string deleteString = "DELETE Products " + "WHERE ProductID=@ProductID"; SqlCommand cmd = new SqlCommand(deleteString, con); cmd.Parameters.AddWithValue("@ProductId", original_productId); con.Open(); cmd.ExecuteNonQuery(); con.Close(); } }
您可以將這個修改過的 ProductInfo 類與清單 6 中包含的ObjectDataSource 控件一起使用,以編輯 Products 數據庫表的內容。
清單 6: ShowProducts3.aspx
<html> <head> <title>Show Products</title> </head> <body> <form id="form1" runat="server"> <asp:GridView ID="GridView1" DataSourceID="ObjectDataSource1" DataKeyNames="ProductId" AutoGenerateColumns="false" AutoGenerateEditButton="true" AutoGenerateDeleteButton="true" Runat="Server"> <Columns> <asp:BoundField DataField="ProductName"/> <asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}"/> </Columns> </asp:GridView> <asp:ObjectDataSource ID="ObjectDataSource1" TypeName="ProductInfo3" SelectMethod="GetProducts" UpdateMethod="UpdateProduct" DeleteMethod="DeleteProduct" Runat="Server"> <UpdateParameters> <asp:Parameter Name="original_productId" Type="Int32" /> <asp:Parameter Name="productName" /> <asp:Parameter Name="unitPrice" Type="Decimal"/> </UpdateParameters> </asp:ObjectDataSource> </form> </body> </html>
在清單 6 中,GridView 控件顯示了ProductName 和 UnitPrice 這兩個列的值。由于 GridView 控件的 AutoGenerateEditButton 和 AutoGenerateDeleteButton 屬性均設置為值 True,GridView 將自動生成用于編輯和刪除產品行的用戶界面(請參見圖 3)。
圖 3. 使用 ObjectDataSource 控件編輯數據
當您單擊 Update 鏈接更新產品時,ObjectDataSource 控件將調用 UpdateProduct 方法。請注意,ObjectDataSource 控件在其 UpdateParameters 元素中列出了傳遞給 UpdateProduct 方法的參數。
有一個參數需要額外進行討論。我們需要將被更新的行的 ProductID 列的值傳遞給 UpdateProduct 方法由于沒有在 GridView 中顯示 ProductID 列,我們必須將 ProductID 列分配給 GridView 控件的 DataKeyNames 屬性。這個列的名稱變為 original_productId,而不是 productId,因為我們正在向 update 方法傳遞 ProductID 列的未編輯版本。
如果您單擊 Delete 鏈接,ObjectDataSource 控件將調用 DeleteProduct 方法。由于 GridView 控件的 DataKeyNames 屬性具有值 ProductId,因此會再次將一個名為 original_productId 的參數自動傳遞給 DeleteProduct 方法。
結合使用 ObjectDataSource 控件和 SqlDataSource 控件
到目前為止,我們已經將 ObjectDataSource 控件與使用 SqlDataReader 對象的組件一起使用,以便檢索數據庫數據。這里還有另一種選擇。即不在組件內使用 SqlDataReader 或 DataSet 等 ADO.NET 對象,而是在組件中使用 SqlDataSource 控件。
您可以在組件中使用 SqlDataSource 控件的這一事實似乎很奇怪。通常,您不在組件中使用控件,因為控件一般具有可視化表示形式,而且控件參與頁面執行生命周期。而 DataSource 控件在這一點上有些特殊。
如果您希望簡化組件中的數據庫訪問代碼,您可以在此組件中使用 SqlDataSource 控件。清單 7 展示了這種方式。
清單 7: ProductInfo4.cs (C#)
using System; using System.Collections; using System.Web.UI; using System.Web.UI.WebControls; public class ProductInfo4 { const string conString = "Server=localhost;Trusted_Connection=true;Database=Northwind"; public static IEnumerable GetProducts() { string selectString = "SELECT * FROM Products"; SqlDataSource dsrc = new SqlDataSource(conString, selectString); dsrc.DataSourceMode = SqlDataSourceMode.DataSet; return dsrc.Select(DataSourceSelectArguments.Empty); } }
清單 7 中,我們實例化了 SqlDataSource 控件的一個新實例。SqlDataSource 的構造函數接受了一個用于數據庫連接字符串的參數和一個用于與 select 命令一起使用的命令文本的參數。接著,將 DataSourceMode 屬性的值設為 DataSet(這里的另一個選項是 DataReader)。最后,在 SqlDataSource 控件的實例上調用 Select 方法,并返回表示來自 Products 數據庫表的所有記錄的 DataView。
您可以將清單 7 中的 ProductInfo 類與清單 8 中包含的 ObjectDataSource 控件一起使用:
清單 8: ShowProducts4.aspx
<html> <head> <title>Show Products</title> </head> <body> <form id="form1" runat="server"> <asp:GridView ID="GridView1" DataSourceID="ObjectDataSource1" Runat="Server" /> <asp:ObjectDataSource ID="ObjectDataSource1" TypeName="ProductInfo4" SelectMethod="GetProducts" Runat="Server" /> </form> </body> </html>
在清單 8 中,GridView 控件綁定到了 ObjectDataSource 控件上。而 ObjectDataSource 控件又調用了 ProductInfo4 類的 GetProducts 方法,以檢索由 GridView 顯示的數據。最后,GetProducts 方法使用 SqlDataSource 控件檢索數據庫數據。
ASP.NET 2.0 Framework 極大地簡化了數據庫訪問,使您可以更輕松地生成簡單和復雜的 ASP.NET 應用程序。如果您需要生成一個簡單的數據庫驅動 Web 應用程序,那么您可以使用新的 SqlDataSource 控件。如果您需要生成一個更為復雜的應用程序或示例,您可以在傳統的 3 層應用程序中使用 ObjectDataSource 控件。
ObjectDataSource 控件使您能夠繼續在數據驅動頁面中使用中間層組件。其主要優勢在于使您無需編寫任何代碼即可綁定到一個組件,從而極大簡化了您的用戶界面。使用 ObjectDataSource 控件,我可以在 3 分鐘 20 秒的時間內生成一個可以顯示 Product 數據庫表的組件和頁面。盡管這種方式花的時間比使用 SqlDataSource 控件長,但我感覺這樣做時頁面的體系結構要好得多。
不含病毒。www.avast.com |
留言列表