欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
ASP.NET MVC 緩存使用示例
http://www.uol123.com/2012/05/28/asp-net-mvc-%E7%BC%93%E5%AD%98%E4%BD%BF%E7%94%A8%E7%A4%BA%E4%BE%8B.html 

msdn
https://msdn.microsoft.com/zh-cn/library/ms178603(v=vs.80).aspx


應該說(shuō),緩存的設計是一門(mén)較為復雜的學(xué)問(wèn),主要考慮的問(wèn)題包括:要不要緩存?要緩存哪些數據?要緩存多少數據?要緩存多久?如何更新緩存(手動(dòng)還是自 動(dòng))?將緩存放在哪里?本文將以較為通俗易懂的方式,來(lái)看一看在MVC3的項目中,如何使用緩存功能。對于上述提到的一些具體業(yè)務(wù)問(wèn)題,我這里不會(huì )進(jìn)行太 過(guò)深入地探討。

為什么需要討論緩存?緩存是一個(gè)中大型系統所必須考慮的問(wèn)題。為了避免每次請求都去訪(fǎng)問(wèn)后臺的資源(例如數據庫),我們一般會(huì )考慮將一些更新不是很 頻繁的,可以重用的數據,通過(guò)一定的方式臨時(shí)地保存起來(lái),后續的請求根據情況可以直接訪(fǎng)問(wèn)這些保存起來(lái)的數據。這種機制就是所謂的緩存機制。

根據緩存的位置不同,可以區分為:

①客戶(hù)端緩存(緩存在用戶(hù)的客戶(hù)端,例如瀏覽器中)

②服務(wù)器緩存(緩存在服務(wù)器中,可以緩存在內存中,也可以緩存在文件里,并且還可以進(jìn)一步地區分為本地緩存和分布式緩存兩種)

 

MVC3中的緩存功能

ASP.NET MVC3 繼承了ASP.NET的優(yōu)良傳統,內置提供了緩存功能支持。主要表現為如下幾個(gè)方面:

①可以直接在Controller,Action或者ChildAction上面定義輸出緩存(這個(gè)做法相當于原先的頁(yè)面緩存和控件緩存功能)

②支持通過(guò)CacheProfile的方式,靈活定義緩存的設置(新功能)

③支持緩存依賴(lài),以便當外部資源發(fā)生變化時(shí)得到通知,并且更新緩存

④支持使用緩存API,還支持一些第三方的緩存方案(例如分布式緩存)

那么,下面我們就逐一來(lái)了解一下

一、范例準備

我準備了一個(gè)空白的MVC 3項目,里面創(chuàng )建好了一個(gè)Model類(lèi)型:Employee

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  5. namespace MvcApplicationCacheSample.Models
  6. {  public class Employee
  7.     {
  8.         public int ID { get; set; }
  9.         public string Name { get; set; }
  10.         public string Gender { get; set; }
  11.     }
  12. }

然后,我還準備了一個(gè)HomeController

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  5. using System.Web.Mvc;
  6. using MvcApplicationCacheSample.Models;
  7. namespace MvcApplicationCacheSample.Controllers
  8. {  public class HomeController : Controller
  9.     {
  10.         //
  11.         // GET: /Home/
  12.         public ActionResult Index()
  13.         {
  14.             //這里目前作為演示,是直接硬編碼,實(shí)際上可能是讀取數據庫的數據
  15.             var employees = new[]{
  16.                 new Employee(){ID=1,Name=”ares”,Gender=”Male”}
  17.             };
  18.             return View(employees);
  19.         }
  20.     }
  21. }
  22.  
  23.    同時(shí),為這個(gè)Action生成了一個(gè)View
  24. @model IEnumerable<MvcApplicationCacheSample.Models.Employee>
  25. @{
  26.     ViewBag.Title = “Index”;
  27. }
  28. <h2>Index</h2>
  29. <p>
  30.     @Html.ActionLink(“Create New”, “Create”)
  31. </p>
  32. <table>
  33.     <tr><th>Name</th>
  34.           <th>Gender</th>
  35.           <th></th>
  36.     </tr>
  37. @foreach (var item in Model) {
  38.     <tr>
  39.         <td>@Html.DisplayFor(modelItem => item.Name)</td>
  40.         <td>@Html.DisplayFor(modelItem => item.Gender)</td>
  41.         <td>
  42.             @Html.ActionLink(“Edit”, “Edit”, new { id=item.ID }) |
  43.             @Html.ActionLink(“Details”, “Details”, new { id=item.ID }) |
  44.             @Html.ActionLink(“Delete”, “Delete”, new { id=item.ID })
  45.         </td>
  46.     </tr>
  47. }
  48. </table>
二、使用輸出緩存  那么,現在我們假設這個(gè)讀取員工的數據很頻繁,但是數據又更新不是很頻繁,我們就會(huì )想到,能不能對這部分數據進(jìn)行緩存,以便減少每次執行的時(shí)間。

是的,我們可以這么做,而且也很容易做到這一點(diǎn)。MVC中內置了一個(gè)OutputCache的ActionFilter,我們可以將它應用在某個(gè)Action或者ChildAction上面

【備注】ChildAction是MVC3的一個(gè)新概念,本質(zhì)上就是一個(gè)Action,但通常都是返回一個(gè)PartialView。通常這類(lèi) Action,可以加上一個(gè)ChildActionOnly的ActionFilter以標識它只能作為Child被請求,而不能直接通過(guò)地址請求。

【備注】我們確實(shí)可以在Controller級別定義輸出緩存,但我不建議這么做。緩存是要經(jīng)過(guò)考慮的,而不是不管三七二十一就全部緩存起來(lái)。緩存不當所造成的問(wèn)題可能比沒(méi)有緩存還要大。

下面的代碼啟用了Index這個(gè)Action的緩存功能,我們讓他緩存10秒鐘。

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  5. using System.Web.Mvc;
  6. using MvcApplicationCacheSample.Models;
  7. namespace MvcApplicationCacheSample.Controllers
  8. {
  9.     public class HomeController : Controller
  10.     {
  11.         //
  12.         // GET: /Home/
  13.         [OutputCache(Duration=10)]
  14.         public ActionResult Index()
  15.         {
  16.             //這里目前作為演示,是直接硬編碼,實(shí)際上可能是讀取數據庫的數據
  17.             var employees = new[]{
  18.                 new Employee(){ID=1,Name=“ares”,Gender=“Male”}
  19.             };
  20.             return View(employees);
  21.         }
  22.     }
  23. }

那么,也就是說(shuō),第一次請求這個(gè)Index的時(shí)候,里面的代碼會(huì )執行,并且結果會(huì )被緩存起來(lái),然后在10秒鐘內,第二個(gè)或者后續的請求,就不需要再次執行,而是直接將結果返回給用戶(hù)即可。

這個(gè)OutputCache的Attribute,實(shí)際上是一個(gè)ActionFilter,它有很多參數,具體的請參考 http://msdn.microsoft.com/zh-cn/library/system.web.mvc.outputcacheattribute.aspx

這些參數中,Duration是必須的,這是設置一個(gè)過(guò)期時(shí)間,以秒為單位,這個(gè)我想大家都很好理解。我重點(diǎn)要一下下面幾個(gè):VaryByContentEncoding、VaryByCustom、VaryByHeader、VaryByParam。

這四個(gè)參數的意思是,決定緩存中如何區分不同請求,就是說(shuō),哪些因素將決定使用還是不使用緩存。默認情況下,如果不做任何設置,那么在規定的時(shí)間內(我們稱(chēng)為緩存期間),所有用戶(hù),不管用什么方式來(lái)訪(fǎng)問(wèn),都是直接讀取緩存。

VaryByParam,可以根據用戶(hù)請求的參數來(lái)決定是否讀取緩存。這個(gè)參數主要指的就是QueryString。例如

如果我們緩存了http://localhost/Home/Index,那么用這個(gè)地址來(lái)訪(fǎng)問(wèn)的時(shí)候,規定時(shí)間內都是讀取緩存。但如果用http://localhost/Home/Index?name=chenxizhang這樣的地址過(guò)來(lái)訪(fǎng)問(wèn),顯然我們希望不要讀取緩存,因為參數不一樣了。要實(shí)現這樣的需求,也就是說(shuō),希望根據name參數的不同緩存不同的數據。則可以設置VaryByParam=”name”。

如果有多個(gè)參數的話(huà),可以用逗號分開(kāi)他們。例如 VaryByParam=”name,Id”

【備注】這里其實(shí)會(huì )有一個(gè)潛在的風(fēng)險,由于針對不同的參數(以及他們的組合)需要緩存不同的數據版本,假設有一個(gè)惡意的程序,分別用不同的參數發(fā)起大量的請求,那么就會(huì )導致緩存爆炸的情況,極端情況下,會(huì )導致服務(wù)器出現問(wèn)題。(當然,IIS里面,如果發(fā)現緩存的內容不夠用了,會(huì )自動(dòng)將一些數據清理掉,但這就同樣導致了程序的不穩定性,因為某些正常需要用的緩存可能會(huì )被銷(xiāo)毀掉)。這也就是我為什么強調說(shuō),緩存設計是一個(gè)比較復雜的事情。

VaryByHeader,可以根據用戶(hù)請求中所提供的一些Header信息不同而決定是否讀取緩存。我們可以看到在每個(gè)請求中都會(huì )包含一些Header信息,如下圖所示

這個(gè)也很有用,例如根據不同的語(yǔ)言,我們顯然是有不同的版本的?;蛘吒鶕脩?hù)瀏覽器不同,也可以緩存不同的版本??梢酝ㄟ^(guò)這樣設置

VaryByHeader=”Accept-Language,User-Agent”

上面兩個(gè)是比較常用的。當然還有另外兩個(gè)屬性也可以設置

VaryByContentEncoding,一般設置為Accept-Encoding里面可能的Encoding名稱(chēng),從上圖也可以看出,Request里面是包含這個(gè)標頭的。

VaryByCustom,則是一個(gè)完全可以定制的設置,例如我們可能需要根據用戶(hù)角色來(lái)決定不同的緩存版本,或者根據瀏覽器的一些小版本號來(lái)區分不同 的緩存版本,我們可以這樣設置:VaryByCustom=”Role,BrowserVersion”,這些名稱(chēng)是你自己定義的,光這樣寫(xiě)當然是沒(méi)有用 的,我們還需要在Global.asax文件中,添加一個(gè)特殊的方法,來(lái)針對這種特殊的需求進(jìn)行處理。

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  5. using System.Web.Mvc;
  6. using System.Web.Routing;
  7. using System.Web.Security;
  8. namespace MvcApplicationCacheSample
  9. {
  10.     // Note: For instructions on enabling IIS6 or IIS7 classic mode,
  11.     // visit http://go.microsoft.com/?LinkId=9394801
  12.     public class MvcApplication : System.Web.HttpApplication
  13.     {
  14.         public static void RegisterGlobalFilters(GlobalFilterCollection filters)
  15.         {
  16.             filters.Add(new HandleErrorAttribute());
  17.         }
  18.         public static void RegisterRoutes(RouteCollection routes)
  19.         {
  20.             routes.IgnoreRoute(“{resource}.axd/{*pathInfo}”);
  21.             routes.MapRoute(
  22.                 “Default”, // Route name
  23.                 “{controller}/{action}/{id}”, // URL with parameters
  24.                 new { controller = “Home”, action = “Index”, id = UrlParameter.Optional } // Parameter defaults
  25.             );
  26.         }
  27.         protected void Application_Start()
  28.         {
  29.             AreaRegistration.RegisterAllAreas();
  30.             RegisterGlobalFilters(GlobalFilters.Filters);
  31.             RegisterRoutes(RouteTable.Routes);
  32.         }
  33.         public override string GetVaryByCustomString(HttpContext context, string custom)
  34.         {
  35.             switch(custom)
  36.             {
  37.                 case “Role”:
  38.                     {
  39.                         return string.Join(“,”, Roles.GetRolesForUser());
  40.                     }
  41.                 case “BrowserVersion”:
  42.                     {
  43.                         return context.Request.Browser.Type;
  44.                     }
  45.                 default:
  46.                     break;
  47.             }
  48.             return string.Empty;
  49.         }
  50.     }
  51. }

上面四個(gè)屬性,可以改變緩存使用的行為。另外還有一個(gè)重要屬性將影響緩存保存的位置,這就是Location屬性,這個(gè)屬性有如下幾個(gè)可選項,我從文檔中摘錄過(guò)來(lái)

這里要思考一個(gè)問(wèn)題,設置為Client與設置為Server有哪些行為上面的不同

如果設置為Client,那么第一次請求的時(shí)候,得到的響應標頭里面,會(huì )記錄好這個(gè)頁(yè)面應該是要緩存的,并且在10秒之后到期。如下圖所示

而如果設置為Server的話(huà),則會(huì )看到客戶(hù)端是沒(méi)有緩存的。

看起來(lái)不錯,不是嗎?如果你不加思索地就表示同意,我要告訴你,你錯了。所以,不要著(zhù)急就下結論,請再試一下設置為Client的情況,你會(huì )發(fā)現, 如果你刷新頁(yè)面,那么仍然會(huì )發(fā)出請求,而且Result也是返回200,這表示這是一個(gè)新的請求,確實(shí)也返回了結果。這顯然是跟我們預期不一樣的。

為了做測試,我特意加了一個(gè)時(shí)間輸出,如果僅僅設置為Client的話(huà),每次刷新這個(gè)時(shí)間都是不一樣的。這說(shuō)明,服務(wù)器端代碼被執行了。

同樣的問(wèn)題也出現在,如果我們將Location設置為ServerAndClient的時(shí)候,其實(shí)你會(huì )發(fā)現Client的緩存好像并沒(méi)有生效,每次都仍然是請求服務(wù)器,只不過(guò)這一種情況下,服務(wù)器端已經(jīng)做了緩存,所以在規定時(shí)間內,服務(wù)器代碼是不會(huì )執行的,所以結果也不會(huì )變。但是問(wèn)題在于,既然設置了客戶(hù)端緩存,那么理應就直接使用客戶(hù)端的緩存版本,不應該去請求服務(wù)器才對。

這個(gè)問(wèn)題,其實(shí)屬于是ASP.NET本身的一個(gè)問(wèn)題,這里有一篇文章介紹 http://blog.miniasp.com/post/2010/03/30/OutputCacheLocation-ServerAndClient-problem-fixed.aspx

我們可以看一下,將Location設置為ServerAndClient, 對代碼稍作修改

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  5. using System.Web.Mvc;
  6. using MvcApplicationCacheSample.Models;
  7. using System.Web.UI;
  8. namespace MvcApplicationCacheSample.Controllers
  9. {
  10.     public class HomeController : Controller
  11.     {
  12.         //
  13.         // GET: /Home/
  14.         [OutputCache(Duration=10,Location=OutputCacheLocation.ServerAndClient)]
  15.         public ActionResult Index()
  16.         {
  17.             Response.Cache.SetOmitVaryStar(true);
  18.             ViewBag.CurrentTime = DateTime.Now.ToString();
  19.             //這里目前作為演示,是直接硬編碼,實(shí)際上可能是讀取數據庫的數據
  20.             var employees = new[]{
  21.                 new Employee(){ID=1,Name=“ares”,Gender=“Male”}
  22.             };
  23.             return View(employees);
  24.         }
  25.     }
  26. }

我們看到,從第二次請求開(kāi)始,狀態(tài)碼是304,這表示該頁(yè)被緩存了,所以瀏覽器并不需要請求服務(wù)器的數據。而且你可以看到Received的字節為221B,而不是原先的1.25KB。

但是,如果僅僅設置為Client,則仍然無(wú)法真正實(shí)現客戶(hù)端緩存(這個(gè)行為是有點(diǎn)奇怪的)。這個(gè)問(wèn)題我確實(shí)也一直沒(méi)有找到辦法,如果我們確實(shí)需要使用客戶(hù)端緩存,索性我們還是設置為ServerAndClient吧。

使用客戶(hù)端緩存,可以明顯減少對服務(wù)器發(fā)出的請求數,這從一定意義上更加理想。

三、使用緩存配置文件

第一節中,我們詳細地了解了MVC中,如何通過(guò)OutputCache這個(gè)ActionFilter來(lái)設置緩存。但是,因為這些設置都是通過(guò)C#代碼直接定義在A(yíng)ction上面的,所以未免不是很靈活,例如我們可能需要經(jīng)常調整這些設置,該如何辦呢?

ASP.NET 4.0中提供了一個(gè)新的機制,就是CacheProfile的功能,我們可以在配置文件中,定義所謂的Profile,然后在OutputCache這個(gè)Attribute里面可以直接使用。

通過(guò)下面的例子,可以很容易看到這種機制的好處。下面的節點(diǎn)定義在system.web中

    <caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name=”employee” duration=”10″ enabled=”true” location=”ServerAndClient” varyByParam=”none”/>
</outputCacheProfiles>
</outputCacheSettings>
</caching>

然后,代碼中可以直接地使用這個(gè)Profile了

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  5. using System.Web.Mvc;
  6. using MvcApplicationCacheSample.Models;
  7. using System.Web.UI;
  8. namespace MvcApplicationCacheSample.Controllers
  9. {
  10.     public class HomeController : Controller
  11.     {
  12.         //
  13.         // GET: /Home/
  14.         [OutputCache(CacheProfile=“employee”)]
  15.         public ActionResult Index()
  16.         {
  17.             //Response.Cache.SetOmitVaryStar(true);
  18.             ViewBag.CurrentTime = DateTime.Now.ToString();
  19.  
  20.             //這里目前作為演示,是直接硬編碼,實(shí)際上可能是讀取數據庫的數據
  21.             var employees = new[]{
  22.                 new Employee(){ID=1,Name=“ares”,Gender=“Male”}
  23.             };
  24.             return View(employees);
  25.         }
  26.     }
  27. }

這個(gè)例子很直觀(guān),有了Profile,我們可以很輕松地在運行時(shí)配置緩存的一些關(guān)鍵值。

使用緩存API

通過(guò)上面的兩步,我們了解到了使用OutputCache,并且結合CacheProfile,可以很好地實(shí)現靈活的緩存配置。但是有的時(shí)候,我們可能 還希望對緩存控制得更加精細一些。因為OutputCache是對Action的緩存,不同的Action之間是不能共享數據的,假如某些數據,我們是在 不同的Action之間共享的,那么,簡(jiǎn)單地采用OutputCache來(lái)做,就會(huì )導致對同一份數據,緩存多次的問(wèn)題。

所以,ASP.NET除了提供OutputCache這種基于聲明的輸出緩存設置之外,還允許我們在代碼中,自己控制要對哪些數據進(jìn)行緩存,并且提供了更多的選項。

關(guān)于如何通過(guò)API的方式添加或者使用緩存,請參考http://msdn.microsoft.com/zh-cn/library/18c1wd61%28v=VS.80%29.aspx

基本上就是使用HttpContext.Cache類(lèi)型,可以完成所有的操作,而且足夠靈活。

值得一提的是,我知道不少公司在項目中都會(huì )采用一些ORM框架,某些ORM框架中也允許實(shí)現緩存。例如NHibernate就提供了較為豐富的緩存功 能,大致可以參考一下 http://www.cnblogs.com/RicCC/archive/2009/12/28/nhibernate-cache-internals.html

需要注意的是,微軟自己提供的Entity Framework本身并沒(méi)有包含緩存的功能。

這里仍然要特別提醒一下,使用這種基于A(yíng)PI的緩存方案,需要仔細推敲每一層緩存的設置是否合理,以及更新等問(wèn)題。

使用緩存依賴(lài)

很早之前,在A(yíng)SP.NET中設計緩存的時(shí)候,我們就可以使用緩存依賴(lài)的技術(shù)。關(guān)于緩存依賴(lài),詳細的信息請參考 http://msdn.microsoft.com/zh-cn/library/ms178604.aspx

實(shí)際上,這個(gè)技術(shù)確實(shí)很有用,ASP.NET默認提供了一個(gè)SqlCacheDependency,可以通過(guò)配置,連接SQL Server數據庫,當數據庫的表發(fā)生變化的時(shí)候,會(huì )通知到ASP.NET,該緩存就會(huì )失效。

值得一提的是,不管是采用OutputCache這樣的聲明式的緩存方式,還是采用緩存API的方式,都可以使用到緩存依賴(lài)。而且使用緩存API的話(huà), 除了使用SqlCacheDependency之外,還可以使用標準的CacheDependency對象,實(shí)現對文件的依賴(lài)。

分布式緩存

上面提到的手段都很不錯,如果應用系統不是很龐大的話(huà),也夠用了。需要注意的是,上面所提到的緩存手段,都是在Web服務(wù)器本地內存中進(jìn)行緩存,這種做法的問(wèn)題在于,如果我們需要做負載均衡(一般就會(huì )有多臺服務(wù)器)的時(shí)候,就不可能在多臺服務(wù)器之間共享到這些緩存。正因為如此,分布式緩存的概念就應運而生了。

談到分布式緩存,目前比較受到大家認可的一個(gè)開(kāi)源框架是 memcached。顧名思義,它仍然使用的是內存的緩存,只不過(guò),它天生就是基于分布式的,它的訪(fǎng)問(wèn)都是直接通過(guò)tcp的方式,所以可以訪(fǎng)問(wèn)遠程服務(wù)器,也可以多臺Web服務(wù)器訪(fǎng)問(wèn)同一臺緩存服務(wù)器。

需要注意的是,分布式緩存不是為了來(lái)提高性能的(這可能是一個(gè)誤區),并且可以肯定的是,它的速度一定會(huì )被本地慢一些。如果你的應用只有一臺服務(wù)器就能滿(mǎn)足要求,你就沒(méi)有必要使用memcached。它的最大好處就是跨服務(wù)器,跨應用共享緩存。

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
ASP.NET MVC 教程 -使用輸出緩存提高性能(C#)
[Asp.net mvc]OutputCacheAttribute
asp.net緩存機制 - .net新手 - 博客園
MVC模式在A(yíng)SP.NET中的應用
ASP.net MVC 4 中Security.FormsAuthentication驗證用戶(hù)的狀態(tài)(匿名|已登錄)
Asp.Net MVC中的控制器
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久