Now, with the help of. NET4.0 in the OutputCacheProvider, we can have a variety of options to create our own cache. For example, we can store HTML output cache to memcached distributed Cluster Server, or MongoDB (a common document-oriented database, you may wish to read this article Http://msdn.microsoft.com/zh-cn/magazine/gg650661.aspx)。 Of course, we can also store the cache as a file on the hard disk, considering scalability, which is the cheapest approach, this article is about building custom file caching.
1:outputcacheprovider
OutputCacheProvider is an abstract base class, and we need to override four of these methods, respectively:
Add method to insert the specified item into the output cache.
Get method, which returns a reference to the specified item in the output cache.
The Remove method to remove the specified item from the output cache.
A set method that inserts the specified item into the output cache, overwriting the item if it is already cached.
2: Create your own file cache processing class
The type is filecacheprovider and the code is as follows:
Copy Code code as follows:
public class Filecacheprovider:outputcacheprovider
{
private static readonly ILog log = Logmanager.getlogger (System.Reflection.MethodBase.GetCurrentMethod (). DeclaringType);
public override void Initialize (string name, NameValueCollection attributes)
{
Base. Initialize (name, attributes);
CachePath = HttpContext.Current.Server.MapPath (attributes["CachePath"));
}
public override Object Add (string key, Object entry, DateTime utcexpiry)
{
Object obj = Get (key);
if (obj!= null)//This step is important
{
return obj;
}
Set (Key,entry,utcexpiry);
return entry;
}
public override object Get (String key)
{
String path = Convertkeytopath (key);
if (! File.exists (PATH))
{
return null;
}
CacheItem item = NULL;
using (FileStream file = file.openread (path))
{
var formatter = new BinaryFormatter ();
Item = (CacheItem) formatter. Deserialize (file);
}
if (item. Expirydate <= DateTime.Now.ToUniversalTime ())
{
Log. Info (item. Expirydate + "*" + key);
Remove (key);
return null;
}
return item. Item;
}
public override void Set (string key, Object entry, DateTime utcexpiry)
{
CacheItem item = new CacheItem (entry, utcexpiry);
String path = Convertkeytopath (key);
using (FileStream file = file.openwrite (path))
{
BinaryFormatter formatter = new BinaryFormatter ();
Formatter. Serialize (file, item);
}
}
public override void Remove (string key)
{
String path = Convertkeytopath (key);
if (file.exists (path))
File.delete (path);
}
public string CachePath
{
Get
Set
}
private string Convertkeytopath (String key)
{
string file = key. Replace ('/', '-');
File + = ". txt";
Return Path.Combine (CachePath, file);
}
}
[Serializable]
public class CacheItem
{
Public DateTime expirydate;
public object Item;
Public CacheItem (Object entry, DateTime utcexpiry)
{
Item = entry;
Expirydate = Utcexpiry;
}
}
There are two places that need special instructions:
In the Add method, there is a condition that must be done, otherwise the caching mechanism will cache the first result, after the expiration period, the cache is invalidated and not rebuilt;
In the sample program, we simply put the cache in the cached directory, in the actual project practice, considering that the cached pages will be thousands of, so we have to do directory rating, otherwise look for and read cache files will become an efficiency bottleneck, which will exhaust the CPU.
3: Configuration file
We need to configure the cache handler in Web.config is a custom filecacheprovider that adds a node under <system.web>:
Copy Code code as follows:
<caching>
<outputcache defaultprovider= "Filecache" >
<providers>
<add name= "Filecache" type= "MvcApplication2.Common.FileCacheProvider" cachepath= "~/cache"/>
</providers>
</outputCache>
</caching>
4: Use of caching
We assume that in the control of MVC (if used in the ASP.net page, the page contains <% @OutputCache varybyparam= "None" duration= "%>"), as you can see, Index is not output-cached, and INDEX2 has an output cache that has a cache time of 10 seconds.
Copy Code code as follows:
public class Homecontroller:controller
{
private static readonly ILog log = Logmanager.getlogger (System.Reflection.MethodBase.GetCurrentMethod (). DeclaringType);
static string s_conn = "Data source=192.168.0.77;initial catalog=luminjidb; User Id=sa; Password=sa; ";
Public ActionResult Index ()
{
using (DataSet ds = Common.SqlHelper.ExecuteDataset (S_conn, CommandType.Text, "select" 1* from Nametb A, DEPTB b where A.depid = b.id ORDER by NEWID ()))
{
Viewbag.message = ds. Tables[0]. rows[0]["Name"]. ToString ();
}
return View ();
}
[OutputCache (Duration = ten, VaryByParam = "None")]
Public ActionResult Index2 ()
{
using (DataSet ds = Common.SqlHelper.ExecuteDataset (S_conn, CommandType.Text, "select" 1* from Nametb A, DEPTB b where A.depid = b.id ORDER by NEWID ()))
{
Viewbag.message = ds. Tables[0]. rows[0]["Name"]. ToString ();
}
return View ();
}
}
5: View the effect
The above code, after accessing the INDEX2, will produce a cached file under the cache folder, as follows:
Now, we start to evaluate the performance comparison between output cache and no output cache, and simulate 100 users with 1000 requests as follows:
As you can see, with output caching, throughput is significantly increased by 10 times times.
6: Code Download
Filecacheprovider's original code came from the network, I modified the bug, all the code downloaded as follows: Mvcapplication20110907.rar