如果使用正確,DataSets能戲劇性地提高你Web站點的性能,然而,如果使用不正確,DataSets會浪費寶貴的服務器資源並降低Web Site的性能。爲了更好地使用DataSets,DataSets可以被cache在存儲器中,響應來自同樣的或是不同的頁面多個請求
Caching DataSets
你可以通過cache對象來緩存DataSet,DataTable或者DataView,爲了緩存DataSet,你應該使用這樣的語句,比如: Cache( "CachedDataSet" ) = dstDataSet ,這個語句增加了一個叫做 CachedDataSet 的項,然後將名爲dstDataSet 的 DataSet 賦值給它
應該意識到,當系統資源變得很少或是應用程序重新啓動,緩存中的項是會被移除的,換句話說,你沒有考慮到當這個項不存在的情況。爲了在任何時候都能從項獲得cache對象,你應該這樣寫:
dstDataSet = Cache( "CachedDataSet" )
If myDataSet Is Nothing Then
' Recreate the DataSet
Cache( "CachedDataSet" ) = dstDataSet
End If
當要從cache中取數據時,總是檢查這個項是否存在,如果不是,重新創建並把這個項重新添加到cache
注意
你必須使用“Is”而不是“=”來比較 cache 中的內容是否存在,你必須使用這個操作符是因爲你要比較的是對象,而不是值。
Displaying Cached Data
假設,你正在構建網上商店,想要把 Products 表的一列商品顯示在 DataGrid 上,或者是,你想要是你的顧客把商品分類顯示在不同的列上。這種情況下,當顧客每次分類商品時,數據沒有變化,只是數據的順序改變了,就沒有必要重新從數據庫列出商品。如下面的例子。
Listing 12.21 CacheProducts.aspx
<%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.SqlClient" %> <Script Runat="Server"> Sub Page_Load If Not IsPostBack Then ' Bind to datagrid dgrdProducts.DataSource = GetProducts() dgrdProducts.DataBind() End If End Sub Function GetProducts() As DataView Dim dstProducts As DataSet Dim conNorthwind As SqlConnection Dim dadProducts As SqlDataAdapter Dim dvwProducts As DataView dvwProducts = Cache( "Products" ) If dvwProducts Is Nothing Then dstProducts = New DataSet() conNorthwind = New SqlConnection( "Server=localhost;UID=sa;PWD=secret;Database=Northwind" ) dadProducts = New SqlDataAdapter( "Select * from Products", conNorthwind ) dadProducts.Fill( dstProducts, "Products" ) dvwProducts = dstProducts.Tables( "Products" ).DefaultView() Cache( "Products" ) = dvwProducts End If Return dvwProducts End Function Sub dgrdProducts_SortCommand( s As Object, e As DataGridSortCommandEventArgs ) Dim dvwProducts As DataView ' Sort DataView dvwProducts = GetProducts() dvwProducts.Sort = e.SortExpression ' Rebind to DataGrid dgrdProducts.DataSource = dvwProducts dgrdProducts.DataBind() End Sub </Script> <html> <head><title>CacheProducts.aspx</title></head> <body> <form Runat="Server"> <asp:DataGrid ID="dgrdProducts" AllowSorting="True" OnSortCommand="dgrdProducts_SortCommand" Runat="Server" /> </form> </body> </html>
Figure 12.10. Sorting cached products.
在cache中緩存商品戲劇性地改變ASP.NET頁面的性能,通過存儲在內存中的商品,數據庫不必要每次頁面請求就重新查詢一遍,還能保證每次商品都是存在的。如果你要改變商品列表,你可以通過以下代碼移除 Products 項
Cache.Remove( "Products" )
Filtering Cached Data
你可以允許用戶去選擇一個分類來顯示相對應的商品類表,Categories 表和 Products 可以被同時存放在 cache 。 當某個商品類型被選中了,你可以從 cache 中篩選出這個類型的商品。代碼如下:
Listing 12.22 CacheStore.aspx
<%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.SqlClient" %> <Script Runat="Server"> Dim dstStore As DataSet Sub Page_Load Dim conNorthwind As SqlConnection Dim dadNorthwind As SqlDataAdapter dstStore = Cache( "Store" ) If dstStore Is Nothing Then dstStore = New DataSet() conNorthwind = New SqlConnection( "Server=localhost;UID=sa;PWD=secret;Database=Northwind" ) dadNorthwind = New SqlDataAdapter( "Select CategoryID, CategoryName From Categories", conNorthwind ) conNorthwind.Open() dadNorthwind.Fill( dstStore, "Categories" ) dadNorthwind.SelectCommand = New SqlCommand( "Select * From Products", conNorthwind ) dadNorthwind.Fill( dstStore, "Products" ) conNorthwind.Close() Cache( "Store" ) = dstStore End If If Not IsPostBack Then dgrdCategories.DataSource = dstStore dgrdCategories.DataMember = "Categories" dgrdCategories.DataBind() End If End Sub Sub dgrdCategories_ItemCommand( s As Object, e As DataListCommandEventArgs ) Dim dvwProducts As DataView Dim intCategoryID ' Select the Chosen Category dgrdCategories.SelectedIndex = e.Item.ItemIndex ' Get CategoryID from DataKeys Collection intCategoryID = dgrdCategories.DataKeys( e.Item.ItemIndex ) ' Filter the Products dvwProducts = dstStore.Tables( "Products" ).DefaultView() dvwProducts.RowFilter = "CategoryID=" & intCategoryID dgrdProducts.DataSource = dvwProducts dgrdProducts.DataBind() End Sub </Script> <html> <head><title>CacheStore.aspx</title></head> <body> <form Runat="Server"> <table width="100%"> <tr><td valign="top" width="200"> <asp:DataList ID="dgrdCategories" OnItemCommand="dgrdCategories_ItemCommand" SelectedItemStyle-BackColor="Yellow" DataKeyField="CategoryID" Runat="Server"> <ItemTemplate> <asp:LinkButton Text='<%# Container.DataItem( "CategoryName" ) %>' Runat="Server" /> </ItemTemplate> </asp:DataList> </td><td valign="top"> <asp:DataGrid ID="dgrdProducts" Runat="Server" /> </td></tr> </table> </form> </body> </html>
Figure 12.11. Filtering a cached DataSet.
Finding a Row in a Cached DataSet
Imagine that your company wants to build a private intranet Web site that contains a directory of employees. Suppose, furthermore, that your company wants to create a form that enables a user to search through the list of employees to display information on a particular employee (the employee name, phone number, and so on).
你可以緩存所有的僱員信息在 DataView,爲了顯示某個特殊僱員的詳細信息,你可以使用 cache 中 DataView 的 Find 函數。如:
Listing 12.23 CacheEmployees.aspx
<%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.SqlClient" %> <Script Runat="Server"> Sub Button_Click( s As Object, e As EventArgs ) Dim dstEmployees As DataSet Dim conNorthwind As SqlConnection Dim dadEmployees As SqlDataAdapter Dim dvwEmployees As DataView Dim arrValues( 1 ) As Object Dim intEmployeeIndex As Integer ' Get cached DataView dvwEmployees = Cache( "Employees" ) If dvwEmployees Is Nothing Then dstEmployees = New DataSet() conNorthwind = New SqlConnection( "Server=localhost;UID=sa;PWD=secret;Database=Northwind" ) dadEmployees = New SqlDataAdapter( "Select * From Employees", conNorthwind ) dadEmployees.Fill( dstEmployees, "Employees" ) dvwEmployees = dstEmployees.Tables( "Employees" ).DefaultView() dvwEmployees.Sort = "LastName, FirstName" Cache( "Employees" ) = dvwEmployees End If ' Find the employee arrValues( 0 ) = txtLastName.Text arrValues( 1 ) = txtFirstName.Text intEmployeeIndex = dvwEmployees.Find( arrValues ) If intEmployeeIndex <> -1 Then lblName.Text = txtLastName.Text & ", " & txtFirstName.Text lblPhone.Text = dvwEmployees( intEmployeeIndex ).Row( "HomePhone" ) lblNotes.Text = dvwEmployees( intEmployeeIndex ).Row( "Notes" ) Else lblError.Text = "Employee Not Found!" End If End Sub </Script> <html> <head><title>CacheEmployees.aspx</title></head> <body> <h2>Employee Directory</h2> <form Runat="Server"> <b>First Name:</b> <asp:TextBox ID="txtFirstName" Runat="Server" /> <p> <b>Last Name:</b> <asp:TextBox ID="txtLastName" Runat="Server" /> <asp:Button Text="Find!" OnClick="Button_Click" Runat="Server" /> <hr> <asp:Label ID="lblError" ForeColor="Red" EnableViewState="False" Runat="Server" /> <asp:Label ID="lblName" EnableViewState="False" Runat="Server" /> <p> <asp:Label ID="lblPhone" EnableViewState="False" Runat="Server" /> <p> <asp:Label ID="lblNotes" EnableViewState="False" Runat="Server" /> </form> </body> </html>