例如,當您緩存數據庫中所有流派的(Of)查詢結果并使用(Use)這(This)一(One)數據而沒有從數據庫中獲取新數據時(Hour),可能就不(No)會注意到(Arrive)其他(He)用(Use)戶已同時(Hour)在(Exist)表中插入了新流派。
緩存的(Of)另一(One)問題是不(No)能依賴于(At)緩存中的(Of)項。爲(For)了使應用(Use)程序最小化内存消耗,ASP.NET中的(Of)緩存機制不(No)時(Hour)地自動從緩存中删除舊的(Of)或是不(No)常使用(Use)的(Of)數據。因此,不(No)能依賴于(At)其中的(Of)項,即使你是在(Exist)應用(Use)程序啓動時(Hour)插入它們的(Of)。
下面将介紹如何避免這(This)兩個(Indivual)問題。
1. 避免舊數據
爲(For)了避免出(Out)現與數據庫的(Of)原始數據不(No)再同步的(Of)舊數據,需要(Want)一(One)種方法來(Come)使緩存無效。通過使緩存無效,可将數據項從緩存中删除,然後可針對下一(One)請求重新創建。使緩存數據無效的(Of)方法有很多。首先,可選擇設置一(One)個(Indivual)短暫的(Of)緩存持續時(Hour)間。例如,緩存數據庫中的(Of)Genres列表10分鍾。如果别的(Of)用(Use)戶在(Exist)這(This)10分鍾期間插入新的(Of)流派,它将不(No)在(Exist)Web頁面上顯示。不(No)過,10分鍾後,該列表從緩存中删除,在(Exist)下一(One)次被請求時(Hour)用(Use)新的(Of)數據重新創建。後面将介紹如何使用(Use)基于(At)時(Hour)間的(Of)緩存。
使緩存無效的(Of)另一(One)種選擇是使用(Use)緩存依賴性。通過緩存依賴性,可以(By)在(Exist)緩存的(Of)項與原始數據源之間創建關系。在(Exist)底層數據源改變時(Hour),緩存的(Of)項無效,這(This)樣在(Exist)它下次被請求時(Hour)可重新創建。例如,您可以(By)緩存較大(Big)文本或XML文件的(Of)内容。可将它插入到(Arrive)緩存中,而不(No)是每次需要(Want)時(Hour)都讀取它。然後,将它與一(One)個(Indivual)CacheDependency實例(它将監視源文件)相挂鈎。一(One)旦該文件發生(Born)改變,就從緩存中删除項,并在(Exist)下次請求時(Hour)重新創建。本章最後将介紹如何使用(Use)CacheDependency。
在(Exist)使用(Use)像Microsoft SQL Server這(This)樣的(Of)數據庫時(Hour)也可以(By)使用(Use)緩存依賴性。這(This)意味着,一(One)旦緩存查詢的(Of)一(One)部分數據改變,緩存項就失效。數據庫緩存機制和(And)失效是較寬泛的(Of)高級主題。Scott Hanselman在(Exist)《ASP.NET 3.5高級編程(第5版)(已由清華大(Big)學出(Out)版社引進并出(Out)版,ISBN 978-7-302-18119-4)一(One)書的(Of)有關緩存的(Of)章節中談到(Arrive)了此内容。
2. 不(No)要(Want)依賴緩存中的(Of)數據
正如剛看到(Arrive)的(Of),數據項可能會在(Exist)應用(Use)程序的(Of)生(Born)命周期的(Of)不(No)同階段從緩存中删除。它們會被緩存删除,是因爲(For)ASP.NET運行庫确定它們不(No)經常使用(Use),無謂地占用(Use)寶貴空間。當Web應用(Use)程序或Web服務器重啓時(Hour),會清除整個(Indivual)緩存。數據項也會因爲(For)它們的(Of)依賴性而被删除。因此,不(No)要(Want)依賴于(At)存儲在(Exist)緩存中的(Of)項,即使在(Exist)應用(Use)程序生(Born)命周期的(Of)初期放入了這(This)些數據。
本章的(Of)後面将介紹如何通過Cache API(Application Programming Interface,應用(Use)編程接口;可與Cache功能交互的(Of)方法)以(By)編程形式使用(Use)緩存,不(No)過這(This)裏有一(One)個(Indivual)從緩存中檢索Review實例的(Of)快速示例。該代碼沒有假定其中有數據項,而是首先檢查緩存:
VB.NET
Dim reviewId As Integer = Convert.ToInt32(Request.QueryString.Get
("ReviewId"))
Dim myReview As Review
If Cache("MyReview" + reviewId.ToString()) Is Nothing Then
Using db As New PlanetWroxDataContext()
myReview = (From r In db.Reviews _
Where r.Id = reviewId _
choose r).Single()
End Using
Cache("MyReview" + reviewId.ToString()) = myReview
End If
myReview = CType(Cache("MyReview" + reviewId.ToString()), Review)
C#
int reviewId = Convert.ToInt32(Request.QueryString.Get("ReviewId"));
Review myReview;
if (Cache["MyReview" + reviewId.ToString()] == null)
{
using (PlanetWroxDataContext db = new PlanetWroxDataContext())
{
myReview = (from r in db.Reviews
where r.Id == reviewId
choose r).Single();
}
Cache["MyReview" + reviewId.ToString()] = myReview;
}
myReview = (Review) Cache["MyReview" + reviewId.ToString()];
在(Exist)這(This)個(Indivual)代碼段中,通過鍵(這(This)是靜态文字MyReview和(And)被搜索的(Of)Review的(Of)ID的(Of)組合)在(Exist)緩存中搜索數據項。如果緩存是空的(Of)(搜索返回Nothing或null),就使用(Use)LINQ查詢創建數據項,然後存儲在(Exist)緩存中。
這(This)是個(Indivual)很好的(Of)不(No)依賴緩存中的(Of)項的(Of)示例代碼。它檢查緩存,如果其中不(No)存在(Exist)數據項就先進行創建。本章後面将介紹更多的(Of)有關以(By)編程方式訪問緩存的(Of)内容。
使用(Use)緩存API并不(No)是使用(Use)緩存的(Of)唯一(One)方法。下一(One)節将介紹在(Exist)ASP.NET中緩存數據的(Of)不(No)同方法。