關于 ASP.NET 內存緩存你需要知道的 10 點

緩存機制的主要目的是提高應用程序的性能。作為 ASP.NET 開發人員,你可能會意識到 ASP.NET Web 窗體以及 ASP.NET MVC 可以使用 Cache 對象緩存應用程序的數據。這通常被稱為服務器端數據緩存,并且常作為框架的內置功能。雖然 ASP.NET Core 中并沒有這樣的 Cache 對象,但是你可以很容易地實現內存緩存。本文將向你說明如何實現。

在進一步閱讀之前,你先創建一個基于 Web 應用程序項目模板的新的 ASP.NET Core 應用程序。

4418040-1c0a4af35d7042d1

然后按照下面提到的步驟逐一構建和測試由內存緩存提供的各種功能。

1. 內存緩存需要在啟動類 Startup 中啟用一下

不同于 ASP.NET Web 窗體和 ASP.NET MVC,ASP.NET Core 沒有內置的 Cache 對象,可以拿來在控制器里面直接使用。 這里,內存緩存時通過依賴注入來啟用的,因此第一步就是在 Startup 類中注冊內存緩存的服務。如此,就得打開?Startup 類然后定位到 ConfigureServices() 方法,像下面這樣修改 ConfigureServices() 方法:

publicvoidConfigureServices(IServiceCollection services){? ? services.AddMvc();? ? ? ? services.AddMemoryCache();}

為了向你的應用程序加入內存緩存能力,你需要在服務集合上調用 AddMemoryCache() 方法。采用這種辦法就可以讓一個內存緩存(它是一個 IMemoryCache 對象)的默認實現可以被注入到控制器中去。

2. 內存緩存使用依賴注入來注入緩存對象

然后打開 HomeController 并對其進行修改,如下所示:

publicclassHomeController:Controller{privateIMemoryCache cache;publicHomeController(IMemoryCache cache){this.cache = cache;? ? }? ? ....}

如你所見,上述代碼聲明了一個 ImemoryCache 的私有變量。該變量會被構造器中被賦值。構造器會通過 DI(依賴注入)接收到緩存參數,然后被存儲在本地變量總,提供后續使用。

3. 你可以使用 Set() 方法來在緩存中存東西

等你有了這個 IMemoryCache 對象,就可以讀取或者向它寫入數據了。向緩存寫入數據項是相當直接的。

publicIActionResultIndex(){? cache.Set("timestamp", DateTime.Now.ToString());returnView();}

上述代碼在 Index() 這個 action 中設置了一個緩存項。這是通過使用 IMemoryCache 的?Set() 來完成的。Set() 方法的第一個參數是鍵名,用來標識該數據項。第二個參數是鍵的取值。在此例中,我們存儲一個字符串的鍵和一個字符串的值,而你也可以存儲其它類型 (原生以及自定義的類型) 的鍵值對。

4. 你可以使用 Get 方法來從緩存中獲取到一個數據項

等你向緩存中添加好了數據,也許會想要在應用程序的其它地方去獲取到該數據,可以用?Get() 來做到。如下代碼會告訴你如何來做這件事情。

public IActionResultShow(){stringtimestamp= cache.Get("timestamp");? return View("Show",timestamp);

}

上述代碼從 HomeController 的另外一個action(Show)那里獲取到了一個緩存的數據項。Get() 方法會指定數據項的類型以及它的鍵名。如果該數據項存在的話,就會被返回并且被賦值給 timestamp 這個字符串變量。然后這個?timestamp 的值就會被傳遞給 Show 視圖。

Show 視圖只是簡單地輸出了 timestamp 的值,如下所示:

TimeStamp : @Model

@Html.ActionLink("Go back","Index","Home")

為了對目前為止你所寫的代碼進行一下測試,請運行應用程序。首先將瀏覽器導航至?/Home/Index ,這樣 timestamp 鍵就會被賦值。然后導航至 /Home/Show 并查看 timestamp 值是否會輸出。下圖所示是 Show() 這個 action 運行起來的一個例子。

4418040-c5506b503ae2b18f.gif

5. 你可以使用 TryGet() 來檢查緩存中是否存在特定的鍵值

如果你觀察前面的示例,會發現每次你導航至 /Home/Index 的時候, 都會有一個新的 timestamp 被賦值給了緩存項。這是因為我們并沒有對此進行檢查,規定只有在數據項不存在的時候才賦值。許多時候你都會想要這樣做的。這里有兩種辦法可以在 Index() 這個 action 里面來做這樣的檢查。我們把兩種辦法都在下面列了出來。

//first wayif(string.IsNullOrEmpty(cache.Get("timestamp"))){? cache.Set("timestamp", DateTime.Now.ToString());}//second wayif(!cache.TryGetValue("timestamp",outstringtimestamp)){? ? cache.Set("timestamp", DateTime.Now.ToString());}

第一種辦法使用了你早先用過的同一個 Get() 方法,這一次它被拿來跟 if 塊一起用。如果 Get() 不能在緩存中找到指定的數據項,IsNullOrEmpty() 就會返回 true。而只有這時候 Set() 才會被調用,一次來添加數據項。

第二種辦法更加優雅一點。它使用 TryGet() 方法來獲取一個數據項。TryGet() 方法會返回一個布爾值來指明數據項有沒有被找到。實際的數據項可以使用一個輸出參數拉取出來。如果 TryGet() 返回false,Set() 就會被用來添加數據。

6. 如果不存在的話,可以使用 GetOrCreate() 來添加一項

有時你需要從緩存中檢索現有項。如果該項目不存在,則希望添加該項。這兩個任務 - 如果它存在獲取值,否則創建之 - 可以使用 GetOrCreate() 方法來實現。修改后的 Show() 方法展示了如何實現的。

publicIActionResultShow(){stringtimestamp = cache.GetOrCreate? ("timestamp", entry => {returnDateTime.Now.ToString(); });returnView("Show",timestamp);}

Show() 動作現在使用 GetOrCreate() 方法。 GetOrCreate() 方法將檢查時間戳的鍵值是否存在。如果是,現有值將被賦值給局部變量。否則,將根據第二個參數中指定的邏輯創建一個新條目并將其添加到緩存中。

為了測試此代碼,請直接運行 /Home/Show,不需要跳轉到 /Home/Index。你仍然會看到輸出的時間戳值,因為在該值不存在的情況下,GetOrCreate() 現在是添加了它。

7. 你可以在一個緩存的數據項上面設置絕對和滾動的過期時間

在前述示例中,一個緩存項只要被添加到緩存就會一直存儲,除非它被明確地使用 Remove() 從緩存中移除。你也可以在一個緩存項上面設置一個絕對和滾動的過期時間。一個絕對的過期設置意味著該緩存項會在嚴格指定的日期和時間點被移除,而滾動過期設置則意味著它在給定的一段時間量處于空閑狀態(也就是沒人去訪問)之后被移除。

為了能在一個緩存項上面設置這兩種過期策略,你要用到 MemoryCacheEntryOptions 對象。如下代碼向你展示了如何去使用。

MemoryCacheEntryOptions options =newMemoryCacheEntryOptions();options.AbsoluteExpiration = DateTime.Now.AddMinutes(1);options.SlidingExpiration = TimeSpan.FromMinutes(1);cache.Set("timestamp", DateTime.Now.ToString(), options);

上述代碼來自于修改過的 Index() action,它創建了一個 MemoryCacheEntryOptions 的對象,然后將它的 AbsoluteExpiration 屬性設置為從此刻到一分鐘之后的一個 DateTime 值,它還將?SlidingExpiration 屬性設置為一分鐘。這些值都指定了該緩存項會在一分鐘之后從緩存移除,不管其是否會被訪問。此外,如果該緩存項如初持續空閑了有一分鐘,它也會被從緩存中移除。

等你將 AbsoluteExpiration 和 SlidingExpiration 的值設置后, Set() 方法就可以被用來將一個數據項添加到緩存。這一次 MemoryCacheEntryOptions 對象會被作為第三個參數傳遞給 Set() 方法。

8. 當緩存項會被移除時,你可以連接回調

有時你會想要在緩存項從緩存中被移除時收到通知。可能會有多種原因需要從緩存中移除數據項。例如,因為明確地執行了?Remove() 方法而移除了一個緩存項, 也有可能是因為它的 AbsoluteExpiration 和 SlidingExpiration 值已經到期而被移除,諸如此類的原因。

為了能知道項目是何時從緩存移除的,你需要編寫一個緩存函數。如下代碼向你展示了如何去做這件事情:

MemoryCacheEntryOptions options =newMemoryCacheEntryOptions();options.AbsoluteExpiration = DateTime.Now.AddMinutes(1);options.SlidingExpiration = TimeSpan.FromMinutes(1);options.RegisterPostEvictionCallback(MyCallback,this);cache.Set("timestamp", DateTime.Now.ToString(), options);

上述代碼同之前使用 MemoryCacheEntryOptions 來配置 AbsoluteExpiration 和 SlidingExpiration 的代碼相當類似。更加重要的是它也調用了 RegisterPostEvictionCallback() 方法來綁定剛剛討論過的回調函數。在這里回調函數被命名為?MyCallback。第二個參數是一個你會想要傳遞給回調函數的狀態對象。這里我們傳入了?HomeController 的實例 (用 this 將當前的 HomeController 對象“點”出來) 作為狀態對象。

前面提到的MyCallback函數,其代碼如下所示:

privatestaticvoidMyCallback(objectkey,objectvalue,EvictionReason reason,objectstate){varmessage = $"Cache entry was removed : {reason}";? ? ((HomeController)state).cache.Set("callbackMessage", message);}

請仔細觀察這段代碼。 MyCallback()?是 HomeController 類里面的一個私有靜態函數,它有四個參數。前面兩個參數表示剛剛刪除的緩存項的鍵和值,第三個參數表示的是該數據項被刪除的原因。EvictionReason 是一個枚舉類型,它維護者各種可能的刪除原因,如過期,刪除以及替換。

在回調函數的內部,我們會基于刪除的原因構造一個字符串消息。我們想要將此消息設置成另外一個緩存項。這樣做的話就需要訪問 HomeController 的緩存對象,此時狀態參數就可以排上用場了。使用狀態對象,你可以對 HomeController 的緩存對象進行控制,并使用 Set()?增加一個 callbackMessage 緩存項。

你可以通過 Show()?這個 action 來訪問到 callbackMessage,如下所示:

public IActionResultShow(){stringtimestamp= cache.Get("timestamp");? ViewData["callbackMessage"] =? ? cache.Get("callbackMessage");? return View("Show",timestamp);

}

最后就可以在 Show 視圖中顯示出來了:

TimeStamp : @Model

@ViewData["callbackMessage"]

@Html.ActionLink("Go back","Index","Home")

歡迎關注我的公眾號(同步更新文章)DoNet技術分享平臺

閱讀原文

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/272640.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/272640.shtml
英文地址,請注明出處:http://en.pswp.cn/news/272640.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

linux git刪除的文件怎么還原,從Git倉庫中恢復已刪除的分支、文件或丟失的commit...

從Git倉庫中恢復已刪除的分支、文件或丟失的commit在使用Git的過程中,有時可能會有一些誤操作比如:執行checkout -f 或 reset -hard 或 branch -d刪除一個分支結果造成本地(遠程)的分支或某些commit丟失可以通過reflog來進行恢復,前提是丟失的…

兩張趣圖助你理解狀態碼的含義~

HTTP狀態碼(HTTP Status Code)是用以表示網頁服務器HTTP響應狀態的3位數字代碼。我們可以通過查看HTTP狀態碼來判斷服務器狀態,常見的有404 、502等;但是其他不是很常見的狀態碼都代表什么狀態呢?下面有兩張有趣的圖片…

java 自定義注解以及獲得注解的值

1.自定義注解 import java.lang.annotation.*;Documented Target(ElementType.FIELD) Inherited Retention(RetentionPolicy.RUNTIME ) public interface MyAnno {/*** 是否能為null* return*/boolean isCanNull() default true;/*** 是否能為空字符串* return*/boolean isCanE…

linux列出管道,lsof列出的管道列表示什么意思?_linux_開發99編程知識庫

文件不僅以流形式打開。 其中一些是在 lsof 手冊中列出的:FD is the File Descriptor number of the file or:cwd current working directory;Lnn library references (AIX);err FD information error (see NAME column);jld jail directory (FreeBSD);ltx shared l…

CSS一些實用的技巧

css 字體簡寫規則當使用css定義字體時你可能會這樣做:font-size: 1em;line-height: 1.5em;font-weight: bold;font-style: italic;font-variant: small-caps;font-family: verdana,serif;事實上你可以簡寫這些屬性:font: 1em/1.5em bold italic small-ca…

linux openssh升級8.1,Centos7利用rpm升級OpenSSH到openssh-8.1p1版本

由于近期安全事故頻發,打算把機器OpenSSH升級到最新版本,找了一圈,發現分享的rpm包就到7.4版本,最新版已經到8.1.p1,所以博客自編譯一個openssh-8.1p1的rpm包進行分享。檢查環境:[roottest]# ssh -VOpenSSH…

《HTTP權威指南》 – 11.驗證碼和新鮮度

服務器應當告知客戶端能夠將內容緩存多長時間,在這個時間內就是新鮮的。服務器可以用這兩個首部之一來提供信息: Expires(過期)Cache - Control(緩存控制)Expires首部 規定文檔“過期”的具體時間&#xff…

產品經理必備神器推薦

歡迎關注我的公眾號(同步更新文章):DoNet技術分享平臺閱讀原文工欲善其事,必先利其器,作為最追求極致體驗的產品經理群體,手里有一件趁手的法器,工作起來才會有一種享受般的快感,最近…

野火linux底板設計,野火STM32F767套件(底板+核心板)

一、兌換形式1、電子芯吧客注冊用戶均可通過免費申請與硬件兌換兩種方式進行申請試用2、免費申請形式為用戶通過分享試用活動至好友,換取申請板卡一次試用資格3、硬件兌換方式為用戶捐贈一塊閑置板卡至電子芯吧客,換取申請板卡一次試用資格4、免費申請渠…

c++ builder xe2 (Embarcadero rad studio) 遠程調試 同樣適用于 delphi 遠程調試 教程

c builder xe2 (Embarcadero rad studio) 遠程調試 同樣適用于 delphi 遠程調試 教程轉載于:https://www.cnblogs.com/LittleTiger/p/5039245.html

JS關閉瀏覽器 (不彈出提示框)

如果網頁不是通過腳本程序打開的(window.open()),調用window.close()腳本關閉窗口前,必須先將window.opener對象置為null,否則瀏覽器(IE7、IE8)會彈出一個確定關閉的對話框。<script…

天大18年c語言離線作業,天大18秋C語言程序設計在線作業一輔導資料.docx-資源下載在線文庫www.lddoc.cn...

天大18秋《C語言程序設計》在線作業一輔導資料.docx天大 18 秋C 語言程序設計 在線作業一1、C 2、D 3、D 4、D 5、D 一、單選題共 40 題,100 分1、設有int a 31,0,3,3,4,5,6,7;,則 a21的值是 A3B5C6D4正確答案是C2、設 int a21,b021; 語句 printf“x,dn”,a,b;的輸出…

AM335x(TQ335x)學習筆記——GPIO關鍵驅動移植

或按照S5PV210學習秩序。我們首先解決的關鍵問題。TQ335x有六個用戶按鈕,每個上、下、剩下、對、Enter和ESC。我想開始學習S5PV210當同一,寫輸入子系統驅動器的關鍵問題要解決,但瀏覽driver/input/keyboardgpio-keys.c,大體上看下…

程序員偷偷深愛的9個不良編程習慣

新媒體管家下面這9個編碼習慣,雖然在編程規則中是被駁斥的,但我們很多人就是會不由自主地使用它們。我們曾經都做過這樣的事情:當媽媽不注意的時候,偷偷地吃糖果零食,然后導致有了蛀牙。同樣的,我們都違背過…

emacs c語言 自動補全,Emacs 與 C/C++ 代碼自動補全

基于 Emacs 的 company 模式并配合 semantic 文法分析器,實現 Emacs 的 C/C 代碼自動補全。關于 Emacs 的代碼自動補全代碼自動補全的功能,對于使用 Emacs 寫代碼的程序員而言其重要性不言而喻的,但是搜了一些所謂的 “Emacs 完美的 C 自動補…

linux(fedora) 下dvwa 建筑環境

linux(fedora)下dvwa組態 1.下載httpd,dvwa,mysql,mysqlserver, php-mysql,php 除了dvwa 這是外界進入下一官方網站。該服務通過休息install 安裝 yum install httpd, mysql, php-mysql, php 假設出現安裝的問題。能夠先yum search xxx 2.安裝完之后,檢查安裝的狀…

c語言一元二次方程 ii(分支嵌套),C程序設計——求一元二次方程算法

要求:從鍵盤上輸入一元二次方程的三個參數,編程判斷并求一元二次方程的實根(a,b,c均為整數)算法分析:一元二次方程是只含有一個未知數,且未知數的最高次數是二次的多項式方程。一元二次方程經過整理都可化成一般形式axbxc0(a≠0)&…

程序員如何優雅度過一生的15個建議

首先,我要說明一下精彩的職業生涯應該是什么樣。他們不是這樣的一個線性圖形,不是每過一個月你就會有對應的成長。(就算是普通的職業生涯也不會這樣。你不會每個月都有提升。每個月你都會變的好一點,但是每次有提升都是大幅度的&a…

cocos2d-x游戲開發 跑酷(四) 關聯與物理世界

原創。轉載注明出處http://blog.csdn.net/dawn_moon/article/details/21451077 前面一節盡管實現了一個跑動的人物,可是他只不過一個精靈在運行一個跑動的幀動畫而已。這一節我要實現精靈和物理世界關聯。讓這個人跟實際的Parkour一樣,有實際體積&#x…

kmp算法的c語言,KMP算法 純C實現

該樓層疑似違規已被系統折疊 隱藏此樓查看此樓我自己寫的KMP算法:int nt[256];void get_next1(char* T, int next[], int tlen){int i 0;int j 1;next[0] -1;while( j {if ( T[i] T[j] ){next[j] 0;i;}else{next[j] i;i 0;}j;}}int Index_KMP1(char* S, cha…