【譯】MVC3 20個秘方-(20 完結)使用緩存讓你的結果加載的更快
問題
隨著您網站的成長,無論是普通的還是動態的內容,這兩個因素導致網站載入變慢。許多用戶造成了大量的web 服務器和數據庫的請求。大量的數據需要強大的數據庫處理能力來支持
它。為了防止花了很多錢,只需添加更多的Web服務器,更聰明的編程,以減少不必要的數據庫或動態處理請求,可以明顯增加你的web應用的整體速度
解決方案
使用OutputCacheAttribute去緩存那些不經常改變或只在具體action改變的數據。
討論
在MVC3中緩存是非常容易的。簡單的添加下邊的attribute在一個controller的一個action上。
[OutputCache (Duration=600)]
這將自動緩存視圖的結果為600秒(或10分鐘)并且共享每個用戶訪問此頁。這意味著,如果你有1000名訪問者訪問在同一頁上,可以減少成千上萬的請求到數據庫。通過簡單的加載一個已經完全處理過的view,可以降低IIS的處理時間。輸出緩存屬性看起來很簡單,但是當你開始尋找下邊的引擎,它可是汽車蓋子下復雜的引擎,除非你是一名機械師。(譯者的意思是,你看起來很簡單,但是內部實現很復雜).這個屬性允許你定義了很多有關如何緩存,從期限到位置,甚至可以添加SQL依賴關系。這將在此配方探討。
緩存的持續時間很簡單:你告訴MVC視圖應該緩存多少秒。位置是更復雜,這可能是客戶端的瀏覽器,服務器,或它們的組合。對需要緩存的數據進行分析是確定在哪做緩存的好方法。如果它是個人數據,例如,一個定制的網頁,緩存在本地用戶的瀏覽器上是一件有意義的事。雖然緩存是偉大的,但也有局限性。通常情況下,主要的限制是內存,不是一切都可以緩存在服務器上。然而,最有趣的選項是SQL依賴關系。 OutputCache允許數據被緩存,直到它實際上是在數據庫中的變化。這是一個非常有用的功能。例如,圖書:不會每天都添加一本新書,所以這個持續時間可以被設置成24小時。然而,如果一本書在緩存過期之前就添加了或者1星期也沒有新書呢?在第一種情況里,一個新的書不會以正確的方式出現,這可能會使用戶不太高興了。在第二個例子里,請求到服務器是不必要的,因為沒有添加的新書。通過啟用SQL依賴關系,如果book 的表變化了,緩存會盡快的重置。這完全是我們希望的效果。
提示:這是一個非常不錯的功能,在其他編程語言時,你需要手動控制緩存。當數據變化時候你需要自己使緩存失效。在這一點上相信我,很容易你就落下了1-2個,忘記清空緩存。
在下邊的例子,緩存將被設置到圖書列表頁。默認的,如果你不在VaryByPararm字段設置任何的值。MVC3 將自動的為每個可變組合創建一個獨立的緩存。這是一個相當不錯的功能。
然而,在這本書的例子中,一個關鍵字搜索字段是作為一個參數被接收的。因為輸入的數以百計,而不是成千上萬的不同的關鍵字組合,這個變量不應該被緩存(見上有關內存警告)。相反的params將被定義成排除這個變量。下面是一個更新的BooksController,使此頁面上的緩存:
using System;
usingSystem.Collections.Generic;
usingSystem.Data;
usingSystem.Data.Entity;
usingSystem.Linq;
usingSystem.Linq.Dynamic;
usingSystem.Web;
usingSystem.Web.Mvc;
usingMvcApplication.Models;
usingMvcApplication.Utils;
usingPagedList;
namespaceMvcApplication.Controllers
{
public class BooksController : Controller
{
privateBookDBContextdb = new BookDBContext();
//
// GET: /Books/
[OutputCache(Duration=600, VaryByParam="sortOrder;filter;page")]
publicViewResult Index(string sortOrder,
string filter, string Keyword, int page = 1)
{
...
return View(books.ToPagedList(currentPage,
maxRecords));
}
...
}
}
此代碼將成為一個不錯的緩存解決方案,并立即減少服務器的負載。這個例子將擴大到包括SQL依賴關系,因為它需要一些安裝工作在開始使用它之前。首先,需要更新Web.config文件。首先,必須定義一個數據庫連接;其次,緩存部分必須被定義為SQL依賴關系如下:
<?xml version="1.0"?>
<configuration>
<connectionStrings>
<add name="ApplicationServices" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;
User Instance=true" providerName="System.Data.SqlClient"/>
<add name="BooksDBContext" connectionString="Server=.\SQLEXPRESS;Database= MvcApplication4.Models.BookDBContext;Trusted_Connection=true"providerName=
"System.Data.SqlClient" />
</connectionStrings>
...
<system.web>
<caching>
<sqlCacheDependency enabled="true" pollTime="2000">
<databases>
<add name = "MvcApplication4.Models.BookDBContext" connectionStringName = "BooksDBContext"/>
</databases>
</sqlCacheDependency>
</caching>
...
</system.web>
...
</configuration>
在上面的例子,pollTime變量設置為2000毫秒,這意味著每2秒,緩存數據庫將查詢改變。這根據您的需求而改變。現在的Global.asax.cs需要更新。在Application_Start函數,
SQL緩存依賴項,必須建立,并且每個需要監聽變化的表要以EnableTableForNotifications功能的SqlCacheDependencyAdmin類建立。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using MvcApplication.Models;
using System.Data.Entity;
using System.Globalization;
using System.Threading;
using MvcApplication.Utils;
namespaceMvcApplication
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
Database.SetInitializer<BookDBContext>(newBookInitializer());
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
String connectionString =System.Configuration.ConfigurationManager.ConnectionStrings["BooksDBContext"].ConnectionString;
System.Web.Caching.SqlCacheDependencyAdmin.EnableNotifications(connectionString);
System.Web.Caching.SqlCacheDependencyAdmin.EnableTableForNotifications(connectionString, "books");
}
}
}
接下來,是一個命令行提示符需要執行幾個動作完成
SQL通知。在Windows中,執行以下步驟:
按開始 - >運行
鍵入cmd,然后按Enter鍵
cd %windir%\Microsoft.NET\Framework\v4.0.30319\
aspnet_regsql.exe -S .\SQLEXPRESS -ed
-d MvcApplication4.Models.BookDBContext -et -t books –E
務必替換您的信息的服務器,數據庫和表名。此外,如果您的數據庫包含用戶名和密碼,你將需要添加額外的輸入他們的參數(- U和- P)。一旦最后的命令運行時,兩個成功的消息應顯示:表明對數據庫中的緩存的成功使,和第二次成功使在指定表上的緩存。最后,BooksController需要稍有變化,使SQL依賴。此外,由于應用程序將被通知的變化,前邊設置很短的時間需要擴展到使用Int32值的最大值。
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Linq.Dynamic;
using System.Web;
using System.Web.Mvc;
using MvcApplication.Models;
using MvcApplication.Utils;
using PagedList;
namespaceMvcApplication.Controllers
{
public class BooksController : Controller
{
privateBookDBContextdb = new BookDBContext();
//
// GET: /Books/
[OutputCache(Duration=Int32.MaxValue, SqlDependency ="MvcApplication4.Models.BookDBContext:books",VaryByParam="sortOrder,filter,page")]
publicViewResult Index(string sortOrder, string filter,
string Keyword, int page = 1)
{
...
return View(books.ToPagedList(currentPage,maxRecords));
}
...
}
}
在以前的MVC版本中,部分緩存不支持,這意味著,只有一個整個action的結果可以被緩存。現在的MVC3支持部分緩存。為了實現這一點,你會像在配方1.14中那樣創建一個child action,Ajax提交表單。在BookCommentsController兩個action只返回一個PartialView,
這些child action都可以緩存無需緩存父action。這是另一個偉大的方式來隔離你的代碼和緩存當某一部分不經常發生變化。
另請參見

浙公網安備 33010602011771號