ASP.NET 缓存(5)

简介:

Building a Custom Cache Provider

创建一个自定义缓存提供

 

下面的例子展示了将每个缓存页面存储在独立的文件中,尽管基于磁盘的缓存比基于内存的慢几个数量级,但使用他也有2个优势。

持久化缓存:因为缓存输出被存储在磁盘上,即使web程序被重启,还是能够存在的。如果这些数据的产生很费开销,这样做还是值得的。

低内存的使用率:当缓存也被使用,他从磁盘直接获得服务。他不需要把数据读回内存。这对于大的缓存页很有用,尤其是对于使用多个参数的查询页输出来说。

尽管这些解决方案工作的很好,但是对于专业的系统来说,不是很精致。

下面的例子演示了如何使用自定义的缓存提供。

例子中主要继承了OutputCacheProvider类,然后把缓存写到磁盘中

public override void Set(string key, object entry, DateTime utcExpiry) 

CacheItem item = new CacheItem(entry, utcExpiry); 
string path = ConvertKeyToPath(key); 
// Overwrite it, even if it already exists. 
using (FileStream file = File.OpenWrite(path)) 

BinaryFormatter formatter = new BinaryFormatter(); 
formatter.Serialize(file, item); 

}

 

具体内容如下:(不翻译了)

 

Table 11-1. Overridable Methods in the OutputCacheProvider 
Method Description 
Initialize() - Gives you a place to perform initialization tasks when the provider is first loaded,such as reading other settings from the web.config file. This is the only method inthis table that you don’t need to override. 
Add() - Adds the item to the cache, if it doesn’t already exist. If the item does exist, this method should take no action. 
Set() - Adds the item to the cache. If the item already exists, this method should overwrite it. 
Get() - Retrieves an item from the cache, if it exists. This method must also enforce timebased expiration, by checking the expiration date and removing the item if necessary. 
Remove() Removes the item from the cache.


In this example, the custom cache provider is called FileCacheProvider: 
public class FileCacheProvider : OutputCacheProvider 

// The location where cached files will be placed. 
public string CachePath 
{ get; set; } 
... 

To perform its serialization, it uses a second class named CacheItem, which simply wraps the initial item you want to cache and the expiration date: 
[Serializable] 
public class CacheItem 

public DateTime ExpiryDate; 
public object Item; 
public CacheItem(object item, DateTime expiryDate) 

ExpiryDate = expiryDate; 
Item = item; 


Now you simply need to override the Add(), Set(), Get(), and Remove() methods. All of these methods receive a key that uniquely identifies the cached content. The key is based on the file name of the cached page. For example, if you use output caching with a page named OutputCaching.aspx in a 
web site named CustomCacheProvider, your code might receive a key like this: 
a2/customcacheprovider/outputcaching.aspx


To translate this into a valid file name, the code simply replaces slash characters (\) with dashes (-). 
It also adds the extension .txt to distinguish this cached content from a real ASP.NET page and to make it easier for you to open it and review its content during debugging. Here’s an example of a transformed file name: 
a2-customcacheprovider-outputcaching.aspx.txt 
To perform this transformation, the FileOutputCacheProvider uses a private method named ConvertKeyToPath():


private string ConvertKeyToPath(string key) 

// Flatten it to a single file name, with no path information. 
string file = key.Replace('/', '-'); 
// Add .txt extension so it's not confused with a real ASP.NET file. 
file += ".txt"; 
return Path.Combine(CachePath, file); 
}


Other approaches are possible—for example, some caching systems use the types from the System.Security.Cryptography namespace to convert the file name to a unique hash value, which looks like a string of meaningless characters. 
Using this method, it’s easy to write the Add() and Set() methods. Remember, the difference between the two is that Set() always stores its content, while Add() must check if it already exists. Add() also returns the cached object. The actual serialization code simply uses the BinaryFormatter to convert the rendered page into a stream of bytes, which can then be written to a file.


public override object Add(string key, object entry, DateTime utcExpiry) 

// Transform the key to a unique filename. 
string path = ConvertKeyToPath(key); 
// Set it only if it is not already cached. 
if (!File.Exists(path)) 

Set(key, entry, utcExpiry); 

return entry; 

public override void Set(string key, object entry, DateTime utcExpiry) 

CacheItem item = new CacheItem(entry, utcExpiry); 
string path = ConvertKeyToPath(key); 
// Overwrite it, even if it already exists. 
using (FileStream file = File.OpenWrite(path)) 

BinaryFormatter formatter = new BinaryFormatter(); 
formatter.Serialize(file, item); 

}

The Get() method is similarly straightforward. However, it must check the expiration date of the retrieved item, and discard it if it has expired: 
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)) 

BinaryFormatter formatter = new BinaryFormatter(); 
item = (CacheItem)formatter.Deserialize(file); 

// Remove expired items. 
if (item.ExpiryDate <= DateTime.Now.ToUniversalTime()) 

Remove(key); 
return null; 

return item.Item; 

Finally, the Remove() method simply deletes the file with the cached data: 
public override void Remove(string key) 

string path = ConvertKeyToPath(key); 
if (File.Exists(path)) File.Delete(path); 
}


Using a Custom Cache Provider 
To use a custom cache provider, you first need to add it inside the &lt;caching> section. Here’s an example that adds the FileCacheProivder and simultaneously sets it to be the default cache provider for all output 
caching: 
<configuration> 
<system.web> 
<caching> 
<outputCache defaultProvider="FileCache"> 
<providers> 
<add name="FileCache" type="FileCacheProvider" cachePath="~/Cache" /> 
</providers> 
</outputCache> 
</caching> 
... 
</system.web> 
</configuration>

This assumes that the FileCacheProvider is a class in the current web application (for example, as a file in the App_Code folder of a projectless web site). If the class were part of a separate assembly, you would need to include the assembly name. For example, a FileCacheProvider in a namespace named CustomCaching and compiled in an assembly named CacheExtensibility would require this configuration: 
<add name="FileCache" type="CustomCaching.FileCacheProvider, CacheExtensibility" 
cachePath="~/Cache" /> 
There’s one other detail here. This example includes a custom attribute, named cachePath. 
ASP.NET simply ignores this added detail, but your code is free to retrieve it and use it. For example, the FileCacheProvider can use the Initialize() method to read this information and set the path (which, in this case, is a subfolder named Cache in the web application folder). 
public override void Initialize(string name, NameValueCollection attributes) 

base.Initialize(name, attributes); 
// Retrieve the web.config settings. 
CachePath = HttpContext.Current.Server.MapPath(attributes["cachePath"]); 

If you don’t use the defaultProvider attribute, it’s up to you to tell ASP.NET when to use its standard in-memory caching service, and when to use a custom cache provider. You might expect to handle this with a directive in the page, but you can’t, simply because caching acts before the page has been retrieved (and, if it’s successful, caching bypasses the page markup altogether).


Instead, you need to override the GetOutputCacheProviderName() method in the global.asax file.This method examines the current request and then returns a string with the name of the cache provider to use while handling this request. Here’s an example that tells ASP.NET to use the FileCacheProvider with the page OutputCaching.aspx (but no other):


public override string GetOutputCacheProviderName(HttpContext context) 

// Get the page. 
string pageAndQuery = System.IO.Path.GetFileName(context.Request.Path); 
if (pageAndQuery.StartsWith("OutputCaching.aspx")) 
return "FileCache"; 
else 
return base.GetOutputCacheProviderName(context); 
}















本文转自cnn23711151CTO博客,原文链接:http://blog.51cto.com/cnn237111/589107 ,如需转载请自行联系原作者









相关文章
|
7月前
|
缓存 开发框架 .NET
ASP.NET Core 缓存
Get新知识: 缓存相关概念:缓存的类型:总结:总的来说,私有缓存会减少网络带宽的需求,同时会减少从缓存到API的请求。因为私有缓存是存储在客户端浏览器的,对于请求来说,如果缓存还在有限期内,那么请求连网络请求都不会发出会直接在客户端浏览器获取到响应,这样就减少网络请求次数,同样也会减少API请求次数。而共享缓存不会节省缓存到API的网路带宽,但是它会减少请求到API的请求。因为共享缓存是...
34 0
ASP.NET Core 缓存
|
10月前
|
存储 SQL 缓存
ASP.NET Core MVC 从入门到精通之缓存
ASP.NET Core MVC 从入门到精通之缓存
87 0
|
存储 缓存 开发框架
Asp.Net Core 2.1+的视图缓存(响应缓存)
Asp.Net Core 2.1+的视图缓存(响应缓存)
68 0
|
存储 消息中间件 缓存
Redis入门与ASP.NET Core缓存
Redis入门与ASP.NET Core缓存
345 0
Redis入门与ASP.NET Core缓存
|
缓存 开发框架 NoSQL
ASP.NET Core 使用Redis实现分布式缓存:Docker、 IDistributedCache、StackExchan geRedis
ASP.NET Core 使用Redis实现分布式缓存:Docker、 IDistributedCache、StackExchan geRedis
286 0
ASP.NET Core 使用Redis实现分布式缓存:Docker、 IDistributedCache、StackExchan geRedis
|
缓存 前端开发 JavaScript
|
缓存 .NET 数据建模
|
Web App开发 缓存 监控
ASP.NET性能优化之反向代理缓存
到目前为止,我们讨论了把缓存存放在ASP.NET的输出缓存中(内存和硬盘),以及浏览器缓存中,而大型站点的另一种常用做法是将缓存部署在反向代理服务器上,这类缓存我们通常称之为反向代理缓存,比如Squid和Varnish。
955 0
|
Web App开发 缓存 JavaScript
ASP.NET性能优化之局部缓存
在网站的开发过程中,经常碰到的一类需求场景是: 1:页面含热点新闻,热点新闻部分需要10分钟更新一次,而整个页面的其它部分1天内都不会变动; 2:首页的某个BANNER需要显式:欢迎***; 上面场景中的1,如果整个页面的缓存失效都定为10分钟,则势必增加性能开销,所以最好的策略是页面的不同部分采用不同的缓存失效时长。
1337 0