例如,當您緩存數(shù)據庫中所有(yǒu)流派的查詢結果并使用這一數(shù)據而沒有(yǒu)從數(shù)據庫中獲取新數(shù)據時(shí),可(kě)能就不會(huì)注意到其他用戶已同時(shí)在表中插入了新流派。
緩存的另一問題是不能依賴于緩存中的項。為(wèi)了使應用程序最小(xiǎo)化內(nèi)存消耗,ASP.NET中的緩存機制(zhì)不時(shí)地自動從緩存中删除舊(jiù)的或是不常使用的數(shù)據。因此,不能依賴于其中的項,即使你(nǐ)是在應用程序啓動時(shí)插入它們的。
下面将介紹如何避免這兩個(gè)問題。
1. 避免舊(jiù)數(shù)據
為(wèi)了避免出現與數(shù)據庫的原始數(shù)據不再同步的舊(jiù)數(shù)據,需要一種方法來(lái)使緩存無效。通(tōng)過使緩存無效,可(kě)将數(shù)據項從緩存中删除,然後可(kě)針對下一請(qǐng)求重新創建。使緩存數(shù)據無效的方法有(yǒu)很(hěn)多(duō)。首先,可(kě)選擇設置一個(gè)短(duǎn)暫的緩存持續時(shí)間(jiān)。例如,緩存數(shù)據庫中的Genres列表10分鍾。如果别的用戶在這10分鍾期間(jiān)插入新的流派,它将不在Web頁面上(shàng)顯示。不過,10分鍾後,該列表從緩存中删除,在下一次被請(qǐng)求時(shí)用新的數(shù)據重新創建。後面将介紹如何使用基于時(shí)間(jiān)的緩存。
使緩存無效的另一種選擇是使用緩存依賴性。通(tōng)過緩存依賴性,可(kě)以在緩存的項與原始數(shù)據源之間(jiān)創建關系。在底層數(shù)據源改變時(shí),緩存的項無效,這樣在它下次被請(qǐng)求時(shí)可(kě)重新創建。例如,您可(kě)以緩存較大(dà)文本或XML文件的內(nèi)容。可(kě)将它插入到緩存中,而不是每次需要時(shí)都讀取它。然後,将它與一個(gè)CacheDependency實例(它将監視(shì)源文件)相挂鈎。一旦該文件發生(shēng)改變,就從緩存中删除項,并在下次請(qǐng)求時(shí)重新創建。本章最後将介紹如何使用CacheDependency。
在使用像Microsoft SQL Server這樣的數(shù)據庫時(shí)也可(kě)以使用緩存依賴性。這意味着,一旦緩存查詢的一部分數(shù)據改變,緩存項就失效。數(shù)據庫緩存機制(zhì)和(hé)失效是較寬泛的高(gāo)級主題。Scott Hanselman在《ASP.NET 3.5高(gāo)級編程(第5版)(已由清華大(dà)學出版社引進并出版,ISBN 978-7-302-18119-4)一書(shū)的有(yǒu)關緩存的章節中談到了此內(nèi)容。
2. 不要依賴緩存中的數(shù)據
正如剛看到的,數(shù)據項可(kě)能會(huì)在應用程序的生(shēng)命周期的不同階段從緩存中删除。它們會(huì)被緩存删除,是因為(wèi)ASP.NET運行(xíng)庫确定它們不經常使用,無謂地占用寶貴空(kōng)間(jiān)。當Web應用程序或Web服務器(qì)重啓時(shí),會(huì)清除整個(gè)緩存。數(shù)據項也會(huì)因為(wèi)它們的依賴性而被删除。因此,不要依賴于存儲在緩存中的項,即使在應用程序生(shēng)命周期的初期放入了這些(xiē)數(shù)據。
本章的後面将介紹如何通(tōng)過Cache API(Application Programming Interface,應用編程接口;可(kě)與Cache功能交互的方法)以編程形式使用緩存,不過這裏有(yǒu)一個(gè)從緩存中檢索Review實例的快速示例。該代碼沒有(yǒu)假定其中有(yǒu)數(shù)據項,而是首先檢查緩存:
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()];
在這個(gè)代碼段中,通(tōng)過鍵(這是靜态文字MyReview和(hé)被搜索的Review的ID的組合)在緩存中搜索數(shù)據項。如果緩存是空(kōng)的(搜索返回Nothing或null),就使用LINQ查詢創建數(shù)據項,然後存儲在緩存中。
這是個(gè)很(hěn)好的不依賴緩存中的項的示例代碼。它檢查緩存,如果其中不存在數(shù)據項就先進行(xíng)創建。本章後面将介紹更多(duō)的有(yǒu)關以編程方式訪問緩存的內(nèi)容。
使用緩存API并不是使用緩存的唯一方法。下一節将介紹在ASP.NET中緩存數(shù)據的不同方法。