在應用程式啟動時快取資料 (VB)
在任何 Web 應用程式中,都會經常使用某些數據,而某些數據則不常使用。 我們可以藉由預先載入常用數據,也就是稱為的技術,來改善 ASP.NET 應用程式的效能。 本教學課程示範主動式載入的一種方法,也就是在應用程式啟動時將數據載入快取。
簡介
先前的兩個教學課程探討在簡報和快取層中快取數據。 在 使用 ObjectDataSource 快取數據中,我們查看了如何使用 ObjectDataSource 的快取功能來快取呈現層中的數據。 在架構中快取數據 會檢查新、個別快取層中的快取。 這兩個教學課程都使用 回應式載入 來處理數據快取。 透過回應式載入,每次要求數據時,系統會先檢查它是否在快取中。 如果沒有,它會從原始來源擷取數據,例如資料庫,然後將它儲存在快取中。 回應式載入的主要優點是其輕鬆實作。 其缺點之一是其跨要求的效能不平均。 假設有一個頁面使用上一個教學課程中的快取層來顯示產品資訊。 當第一次流覽此頁面,或在快取數據因記憶體限制或達到指定的到期日而收回快取數據之後第一次造訪時,必須從資料庫擷取數據。 因此,這些使用者要求所花費的時間會比快取可提供服務的使用者要求更長。
主動式載入 提供替代的快取管理策略,可藉由在需要之前載入快取的數據,讓要求之間的效能順暢。 一般而言,主動式載入會使用一些程式定期檢查,或在基礎數據有更新時收到通知。 此程序接著會更新快取,使其保持最新狀態。 如果基礎數據來自緩慢的資料庫連線、Web 服務或其他某些特別緩慢的數據源,則主動式載入特別有用。 但主動式載入的這個方法較難以實作,因為它需要建立、管理和部署程式來檢查變更並更新快取。
另一種主動式載入,以及我們將在本教學課程中探索的類型,會在應用程式啟動時將數據載入快取。 此方法特別適用於快取靜態數據,例如資料庫查閱數據表中的記錄。
注意
For a more in-depth look at the differences between proactive and reactive loading, as well as lists of pros, cons, and implementation recommendations, refer to the Managing the Contents of a Cache section of the Caching Architecture Guide for .NET Framework Applications.
步驟 1:判斷應用程式啟動時要快取的數據
使用我們在前兩個教學課程中所檢查之回應式載入的快取範例,適用於可能會定期變更的數據,而且不會花費很長的時間來產生。 但是,如果快取的數據永遠不會變更,則反應式載入所使用的到期會不必要。 同樣地,如果快取的數據需要很長的時間才能產生,則要求找到空白快取的用戶必須在擷取基礎數據時等待很長。 請考慮在應用程式啟動時快取需要非常長的時間才能產生的靜態數據和數據。
雖然資料庫有許多動態且經常變更的值,但大部分也都有相當數量的靜態數據。 例如,幾乎所有的數據模型都有一或多個數據行,其中包含一組固定選項中的特定值。 Patients
資料庫數據表可能有一個PrimaryLanguage
數據行,其值集可以是英文、西班牙文、法文、俄文、日文等等。 通常,這些類型的數據行是使用 查閱數據表來實作。 而不是將字串英文或法文儲存在數據表中 Patients
,而是會建立第二個數據表,其中通常會有兩個數據行 ,也就是唯一標識符和字串描述,其中包含每個可能值的記錄。 數據表 PrimaryLanguage
中的數據 Patients
行會將對應的唯一標識符儲存在查閱表格中。 在圖 1 中,病患 John Doe 的主要語言是英文,而 Ed 一位是俄文。
圖 1: Languages
表格是表格所使用的 Patients
查閱表格
編輯或建立新病患的使用者介面會包含數據表中 Languages
記錄填入之允許語言的下拉式清單。 若未快取,每次造訪此介面時,系統都必須查詢 Languages
數據表。 這很浪費且不必要,因為查閱表格值會經常變更,如果有的話。
我們可以使用先前教學課程中所檢查的相同回應式載入技術來快 Languages
取數據。 不過,回應式載入會使用以時間為基礎的到期,這不需要靜態查閱表格數據。 雖然使用回應式載入的快取比完全不快取更好,但最佳方法是在應用程式啟動時主動將查閱表數據載入快取。
在本教學課程中,我們將探討如何快取查閱表數據和其他靜態資訊。
步驟 2:檢查快取數據的不同方式
您可以使用各種方法,以程序設計方式在 ASP.NET 應用程式中快取資訊。 我們已瞭解如何在先前的教學課程中使用數據快取。 或者,可以使用 靜態成員 或 應用程式狀態,以程式設計方式快取物件。
使用類別時,通常必須先具現化類別,才能存取其成員。 例如,為了從商業規則層的其中一個類別叫用方法,我們必須先建立 類別的實例:
Dim productsAPI As New ProductsBLL()
productsAPI.SomeMethod()
productsAPI.SomeProperty = "Hello, World!"
在我們可以叫用 SomeMethod 或使用 SomeProperty 之前,我們必須先使用 New
關鍵詞建立 類別的實例。 SomeMethod 和 SomeProperty 與特定實例相關聯。 這些成員的存留期會系結至其相關聯物件的存留期。 另一方面,靜態成員是類別的所有實例之間共用的變數、屬性和方法,因此只要 類別,就會有存留期。 靜態成員是以 關鍵詞 Shared
表示。
除了靜態成員之外,也可以使用應用程式狀態來快取數據。 每個 ASP.NET 應用程式都會維護跨應用程式所有用戶和頁面共用的名稱/值集合。 您可以使用 類別 s Application
屬性來存取HttpContext
此集合,並從 ASP.NET 頁的程式代碼後置類別使用,如下所示:
Application("key") = value
Dim value As Object = Application("key")
數據快取提供更豐富的 API 來快取數據,提供時間與相依性型到期、快取專案優先順序等機制。 使用靜態成員和應用程式狀態時,頁面開發人員必須手動新增這類功能。 不過,在應用程式啟動時快取數據時,數據快取的優點是無問題。 在本教學課程中,我們將探討使用這三種技術來快取靜態數據的程序代碼。
步驟 3:快取Suppliers
數據表數據
我們實作到最新的 Northwind 資料庫數據表不包含任何傳統的查閱表格。 在 DAL 中實作的四個 DataTable,其值都是非靜態的模型數據表。 在本教學課程中,我們不會花時間將新的 DataTable 新增至 DAL,然後將新的類別和方法新增至 BLL,而是讓我們只假設 Suppliers
數據表的數據是靜態的。 因此,我們可以在應用程式啟動時快取此數據。
若要開始,請在資料夾中建立名為 StaticCache.cs
CL
的新類別。
圖 2:在StaticCache.vb
CL
資料夾中建立 類別
我們需要新增方法,以在啟動時將數據載入適當的快取存放區,以及從這個快取傳回數據的方法。
<System.ComponentModel.DataObject()> _
Public Class StaticCache
Private Shared suppliers As Northwind.SuppliersDataTable = Nothing
Public Shared Sub LoadStaticCache()
' Get suppliers - cache using a static member variable
Dim suppliersBLL As New SuppliersBLL()
suppliers = suppliersBLL.GetSuppliers()
End Sub
<DataObjectMethodAttribute(DataObjectMethodType.Select, True)> _
Public Shared Function GetSuppliers() As Northwind.SuppliersDataTable
Return suppliers
End Function
End Class
上述程式代碼會使用靜態成員變數 suppliers
,來保存類別 s GetSuppliers()
方法的結果SuppliersBLL
,這是從方法呼叫的結果LoadStaticCache()
。 方法 LoadStaticCache()
應該在應用程式啟動時呼叫。 在應用程式啟動時載入此數據之後,任何需要與供應商數據搭配運作的頁面都可以呼叫 StaticCache
類別 s GetSuppliers()
方法。 因此,呼叫資料庫以取得供應商只會在應用程式啟動時發生一次。
我們可以使用應用程式狀態或數據快取,而不是使用靜態成員變數作為快取存放區。 下列程式代碼顯示已重新設定為使用應用程式狀態的 類別:
<System.ComponentModel.DataObject()> _
Public Class StaticCache
Public Shared Sub LoadStaticCache()
' Get suppliers - cache using application state
Dim suppliersBLL As New SuppliersBLL()
HttpContext.Current.Application("key") = suppliers
End Sub
<DataObjectMethodAttribute(DataObjectMethodType.Select, True)> _
Public Shared Function GetSuppliers() As Northwind.SuppliersDataTable
Return TryCast(HttpContext.Current.Application("key"), _
Northwind.SuppliersDataTable)
End Function
End Class
在 LoadStaticCache()
中,供應商資訊會儲存至應用程式變數 索引鍵。 它會以適當的類型傳回, (Northwind.SuppliersDataTable
從 GetSuppliers()
) 。 雖然應用程式狀態可以在使用 Application("key")
ASP.NET 頁面的程式代碼後置類別中存取,但在此架構中,我們必須使用 HttpContext.Current.Application("key")
,才能取得目前的 HttpContext
。
同樣地,數據快取可以當做快取存放區使用,如下列程式代碼所示:
<System.ComponentModel.DataObject()> _
Public Class StaticCache
Public Shared Sub LoadStaticCache()
' Get suppliers - cache using a static member variable
Dim suppliersBLL As New SuppliersBLL()
HttpRuntime.Cache.Insert("key", suppliers, Nothing, _
Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, _
CacheItemPriority.NotRemovable, Nothing)
End Sub
<System.ComponentModel.DataObjectMethodAttribute_
(System.ComponentModel.DataObjectMethodType.Select, True)> _
Public Shared Function GetSuppliers() As Northwind.SuppliersDataTable
Return TryCast(HttpRuntime.Cache("key"), Northwind.SuppliersDataTable)
End Function
End Class
若要將專案新增至數據快取,且沒有以時間為基礎的到期日,請使用 System.Web.Caching.Cache.NoAbsoluteExpiration
和 System.Web.Caching.Cache.NoSlidingExpiration
值作為輸入參數。 已選取這個數據快取方法 Insert
的特定多載,以便我們可以指定快取專案的 優先順序 。 當可用的記憶體執行不足時,會使用優先順序來判斷要從快取中擷取的專案。 在這裡,我們會使用優先順序 NotRemovable
,以確保不會清除此快取專案。
注意
本教學課程會使用靜態成員變數方法來實 StaticCache
作 類別。 應用程式狀態和數據快取技術的程式代碼可在類別檔案的批注中使用。
步驟 4:在應用程式啟動時執行程序代碼
若要在 Web 應用程式第一次啟動時執行程式代碼,我們需要建立名為 Global.asax
的特殊檔案。 此檔案可以包含應用程式層級事件、會話和要求層級事件的事件處理程式,在這裡我們可以新增每當應用程式啟動時執行的程序代碼。
以Global.asax
滑鼠右鍵按兩下 Visual Studio 方案總管 中的網站專案名稱,然後選擇 [新增專案],將檔案新增至 Web 應用程式的根目錄。 從 [新增專案] 對話框中,選取 [全域應用程式類別] 專案類型,然後按兩下 [新增] 按鈕。
注意
如果您的項目中已經有檔案 Global.asax
,[全域應用程式類別] 項目類型將不會列在 [新增專案] 對話框中。
圖 3:將檔案 Global.asax
新增至 Web 應用程式的根目錄 (按兩下以檢視大小完整的映像)
預設 Global.asax
檔案範本包含伺服器端 <script>
標籤的五種方法:
Application_Start
會在 Web 應用程式第一次啟動時執行Application_End
在應用程式關閉時執行Application_Error
每當未處理的例外狀況到達應用程式時,就會執行Session_Start
在建立新的工作階段時執行Session_End
會話過期或放棄時執行
Application_Start
事件處理程式只會在應用程式生命週期期間呼叫一次。 應用程式第一次從應用程式要求 ASP.NET 資源,並繼續執行,直到應用程式重新啟動為止,這可能會因為修改資料夾的內容、修改 Global.asax
、修改資料夾中的內容/Bin
App_Code
或修改Web.config
檔案,以及其他原因而發生。 如需應用程式生命週期的詳細討論 ,請參閱 ASP.NET 應用程式生命週期概觀 。
針對這些教學課程,我們只需要將程式代碼新增至 Application_Start
方法,因此請隨意移除其他教學課程。 在 中 Application_Start
,只要呼叫 StaticCache
類別 s LoadStaticCache()
方法,它會載入並快取供應商資訊:
<%@ Application Language="VB" %>
<script runat="server">
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
StaticCache.LoadStaticCache()
End Sub
</script>
這一切就一切了! 在應用程式啟動時, LoadStaticCache()
此方法會從 BLL 擷取供應商資訊,並將它儲存在靜態成員變數 (,或您最後在類別中使用 StaticCache
的任何快取存放區) 。 若要確認此行為,請在 Application_Start
方法中設定斷點並執行您的應用程式。 請注意,斷點會在應用程式啟動時叫用。 不過,後續的要求不會造成 Application_Start
方法執行。
圖 4:使用斷點確認 Application_Start
事件處理程式正在執行 (按兩下以檢視完整大小的映像)
注意
如果您第一次開始偵錯時未叫用 Application_Start
斷點,這是因為您的應用程式已經啟動。 藉由修改 或 Global.asax
Web.config
檔案來強制應用程式重新啟動,然後再試一次。 您可以直接新增 (或移除) 其中一個檔案結尾的空白行,以快速重新啟動應用程式。
步驟 5:顯示快取的數據
此時,類別 StaticCache
具有在應用程式啟動時快取的供應商數據版本,可透過其 GetSuppliers()
方法存取。 若要從簡報層使用此數據,我們可以使用 ObjectDataSource,或以程式設計方式從 ASP.NET 頁程式代碼後置類別叫 StaticCache
用類別 s GetSuppliers()
方法。 讓我們看看如何使用 ObjectDataSource 和 GridView 控件來顯示快取的供應商資訊。
首先, AtApplicationStartup.aspx
開啟資料夾中的頁面 Caching
。 將 GridView 從 [工具箱] 拖曳至設計工具,並將其 ID
屬性設定為 Suppliers
。 接下來,從 GridView 智慧標記選擇建立名為 SuppliersCachedDataSource
的新 ObjectDataSource。 將 ObjectDataSource 設定為使用 StaticCache
類別 s GetSuppliers()
方法。
圖 5:設定 ObjectDataSource 以使用 StaticCache
類別 (按鍵即可檢視大小完整的映射)
圖 6:使用 GetSuppliers()
方法來擷取快取的供應商數據 (按兩下即可檢視大小完整的影像)
完成精靈之後,Visual Studio 會自動為 中的每個 SuppliersDataTable
數據欄位新增 BoundFields。 您的 GridView 和 ObjectDataSource 宣告式標記看起來應該類似下列:
<asp:GridView ID="Suppliers" runat="server" AutoGenerateColumns="False"
DataKeyNames="SupplierID" DataSourceID="SuppliersCachedDataSource"
EnableViewState="False">
<Columns>
<asp:BoundField DataField="SupplierID" HeaderText="SupplierID"
InsertVisible="False" ReadOnly="True"
SortExpression="SupplierID" />
<asp:BoundField DataField="CompanyName" HeaderText="CompanyName"
SortExpression="CompanyName" />
<asp:BoundField DataField="Address" HeaderText="Address"
SortExpression="Address" />
<asp:BoundField DataField="City" HeaderText="City"
SortExpression="City" />
<asp:BoundField DataField="Country" HeaderText="Country"
SortExpression="Country" />
<asp:BoundField DataField="Phone" HeaderText="Phone"
SortExpression="Phone" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="SuppliersCachedDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetSuppliers" TypeName="StaticCache" />
圖 7 顯示透過瀏覽器檢視時的頁面。 輸出與從 BLL 類別 SuppliersBLL
提取資料相同,但使用 StaticCache
類別會傳回在應用程式啟動時快取的供應商數據。 您可以在 類別 s GetSuppliers()
方法中StaticCache
設定斷點,以確認此行為。
圖 7:快取的供應商數據會顯示在 GridView (按兩下即可檢視大小完整的影像)
摘要
大部分的數據模型都包含相當大量的靜態數據,通常是以查閱表格的形式實作。 由於這項資訊是靜態的,因此每次需要顯示此資訊時,都不需要持續存取資料庫。 此外,由於其靜態本質,在快取數據時不需要到期。 在本教學課程中,我們已瞭解如何採用這類數據,並將其快取在數據快取、應用程式狀態,以及透過靜態成員變數快取。 此資訊會在應用程式啟動時快取,並在整個應用程式的存留期內保留在快取中。
在本教學課程和過去兩個教學課程中,我們已查看應用程式存留期的快取數據,以及使用以時間為基礎的到期日。 不過,快取資料庫數據時,以時間為基礎的到期時間可能小於理想。 相較於定期排清快取,最好只在修改基礎資料庫數據時收回快取的專案。 此理想做法是透過使用 SQL 快取相依性,我們將在下一個教學課程中加以檢查。
快樂的程序設計!
關於作者
Scott Mitchell 是七份 ASP/ASP.NET 書籍的作者,以及 自 1998 年以來與 Microsoft Web 技術合作的 4GuysFromRolla.com 作者。 Scott 是獨立顧問、訓練員和作者。 他的最新書籍是 Sams 在 24 小時內自行 ASP.NET 2.0。 您可以透過mitchell@4GuysFromRolla.com部落格來連線到 ,您可以在 找到http://ScottOnWriting.NET。
特別感謝
本教學課程系列是由許多實用的檢閱者檢閱。 本教學課程的首席檢閱者是 Teresa Murphy 和 Zack Jones。 有興趣檢閱即將推出的 MSDN 文章嗎? 如果是,請將一行 mitchell@4GuysFromRolla.com放在 。
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應