Library tutorials & articles
.NET Data Caching
- Introduction
- Applications, Sessions and Cookies
- Using Data Caching
- Inserting an Item into the Cache
- A Real-World Example
Inserting an Item into the Cache
As we saw earlier, inserting an item into the data cache is as simple as saying Cache(" key ") = value . Items can also be inserted into the cache using the Insert method, which allows for more powerful semantics on how the item in the cache should be handled. Specifically, the Insert method has four overloaded forms, as shown below:
-
Insert(key as String, value as Object)- Inserts the object value into the cache, giving the item the key name key. This is semantically equivalent to usingCache("key") = value. -
Insert(key as String, value as Object, dependencies as CacheDependency)- Inserts the object value into the cache with key name key and dependencies specified by the dependencies parameter. We'll discuss cache dependencies shortly. -
Insert(key as String, value as Object, dependencies as CacheDependency, absoluteExpiration as DateTime, slidingExpiration as TimeSpan)- Inserts the object value into the cache with key name key , dependencies dependencies , and (time-based) expiration policies. Expiration policies, as we'll discuss soon, specify when the item should be evicted from the cache. -
Insert(key as String, value as Object, dependencies as CacheDependency, absoluteExpiration as DateTime, slidingExpiration as TimeSpan, priority as CacheItemPriority, onRemoveCallBack as CacheItemRemovedCallback)- Inserts the object value into the cache with key name key , dependencies dependencies , (time-based) expiration policies, a cache priority, and a callback delegate. The priority specifies how important it is for the cache item to remain in the cache. That is, items with a lower priority will be evicted from the cache before items with a higher priority. The callback delegate provides a means for you to create your own function that is automatically called when the item is evicted from the cache.
The above list of the various forms of the Insert method may look quite daunting. Most often you'll likely use either form 1, 2, or 3. Let's take a moment to discuss the CacheDependency and absolute and sliding time parameters.
Recall that information stored in the data cache is being stored on the Web server's memory. In a pefect world, when an item is added to the cache using Insert( key , value ) or Cache("key") = value , the item will remain in the cache forever. Unfortunately this is not plausible in the real world. If the computer the Web server runs on is rebooted, or shuts off, for example, the cache will be lost. Even if the Web server machine is running, you may lose items from the cache.
To see why, imagine that your Web server has allocated one MB of memory for storing items in the data cache. Now, imaging that you've added a number of items to the data cache such that you've used exactly 1 MB of memory. Great. Now, what happens when you add another item to the data cache? In order for the new item to "fit," the data cache needs to make room for it by removing an existing item. The existing item that is chosen to be removed is said to be evicted .
There may be times when you don't want an item to exist in the cache indefinitely. For example, say that you were displaying an XML file in an ASP.NET DataGrid. Rather than load the XML file into a DataSet and bind the DataSet to the DataGrid each page view, you may opt to cache the DataSet in the data cache. This option would work great until the XML file was altered; at that point, if you were still displaying the cached DataSet the user would be seeing stale information.
To overcome this problem, you can add the DataSet to the data cache, but specify that the XML file it represents is a cache dependency . By setting this file as a cache dependency, when the file changes the DataSet will be automatically evicted from the cache. That means the next time the DataSet is attempted to be read from the cache, it will not be found (since it has been evicted) and will be recreated by repopulating the DataSet from the XML file. This is desired since the XML file has changed since the DataSet was last cached. In order to insert an item with a cache dependency, you can do:
Cache.Insert("key", myDataSet, New CacheDependency(Server.MapPath("data.xml")) )
If you wish to have the cache item evicted from the cache in an absolute time, say, five minutes from when it was inserted into the cache, you can use the third form of the Insert method, whose fourth parameter expects a DateTime value specifying the absolute time. The following code illustrates how to add an item to the cache that will expire five minutes from when it was added and has no cache dependencies:
Cache.Insert("key", value, Nothing, DateTime.Now.AddMinutes(5) , TimeSpan.Zero)
In C# you would use null instead of Nothing to signify that you do not want a cache dependency.
Note that since we do not want to specify a sliding time expiration, we set the last parameter to TimeSpan.Zero . Whereas an absolute time specifies that the item should be evicted from the cache at a specific time, the sliding time eviction parameter specifies that the cache item should be evicted if it is not referenced in a certain timespan. That is, if we set the timespan parameter to, say, TimeSpan.FromSeconds(30) , the cache item will be evicted if it is not referenced within 30 seconds. If it is referenced within 30 seconds, it will be evicted if it's not referenced in another 30 seconds from when it was last referenced, and so on. An example of this would be:
Cache.Insert("key", value, Nothing, DateTime.Now, TimeSpan.FromSeconds(30) , TimeSpan.Zero)
Note that when using the sliding time expiration parameter, the absolute expiration parameter value does not matter. That is, it is automatically set to DateTime.Now and has the sliding time added to it to determine the absolute time the cache item should expire. Of course, if the item is referenced within that time period, the calculation is redone and the absolute expiration time is reset.
Before we move on to some examples, let's take a quick look at the CacheItemRemovedCallback delegate. Recall that you can set this in the fourth overloaded form of the Insert method. The CacheItemRemovedCallback specifies a function that is called when the item has been evicted from the cache. To use the CacheItemRemovedCallback you need to first create a function that has the definition:
Sub CallbackFunction (String, Object, CacheItemRemovedReason)
The CacheItemRemovedReason is an enumeration that explains why the item was removed from the cache. Its entries include:
-
DependencyChanged- the item was removed because its cache dependency was changed. -
Expired- the item was removed because it expired (either by absolute or sliding time expiration). -
Removed- the item was explicitly removed via the Remove method. -
Underused- the item was evicted by the cache because the system needed to free up memory.
To add a CacheItemRemovedCallback function to an added cache item you will need to create the appropriate function and a delegate variable that is wired up to the function, as shown below:
'You would use onCacheRemove as the input parameter for the
'CacheItemRemovedCallback parameter in the fourth form of the Insert method
Dim onCacheRemove As CacheItemRemovedCallback
OnCacheRemove = New CacheItemRemoved(AddressOf Me.CheckCallback)
' Now, create the function
Sub CheckCallback (str As String, obj As Object, reason As CacheItemRemovedReason)
Response.Write ("Cache was removed because : " & reason)
End Sub
I am not going to go into detail discussing the CacheItemPriority option, since I've found very few real-world uses for this property (in designing Web applications). To learn more about this enumeration and how to use it with the Insert see the technical documentation.
Related articles
Related discussion
-
Using FedEx Web Service to Calculcate Shipping Cost
by bhora123 (4 replies)
-
Very Urgent regarding deleting the images from a folder
by rameshbandi (2 replies)
-
Dynamically Generating PDFs in .NET
by nike12 (10 replies)
-
New style of Javascript used in extenders.
by mittalpa (0 replies)
-
Not able to launch the web application
by NaseemAhmed (0 replies)
Related podcasts
-
StackOverflow uses ASP.NET MVC - Jeff Atwood and his technical team
Scott chats with Jeff Atwood of CodingHorror.com and most recently, StackOverflow.com. Jeff and Joel Spolsky and their technical team have created a new class of application using ASP.NET MVC. What works, what doesn't, and how did it all go down?
To Access the Pages Cache from class code c#
Cache ce = new Cache();
ce = System.Web.HttpRuntime.Cache; Lol
So , Does That mean this is a Genuine Microsoft Bug??
ystem.Web.UI.Page {
No matter What If I Use this Syntax[ Colorede red] to acess the Cache Object I get an Exception...
internal class EnvUtil
internal EnvUtil()
{
}
internal string ResetClientID
{
get
{
string sResetClientId="";
try
{
if (Cache["ResetClientDoc"] == null) {
TextReader xt=new StreamReader(Server.MapPath(@"../../Content/EnvReport/ResetClientID.xml"));
sResetClientId=xt.ReadToEnd();
xt.Close();
CacheDependency dep = new CacheDependency(Server.MapPath(@"../../Content/EnvReport/ResetClientID.xml"), DateTime.Now);
Cache.Insert("ResetClientDoc", sResetClientId, dep);
}
else
{
sResetClientId=(string) Cache["ResetClientDoc"];
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
return sResetClientId;
}
}
}
}
Output
?ex.Message
"Cache is not available"
Just because the Cache cannot be inherited, doesn't mean you can't access it when you are inheriting the Page class -
public class MyClass : System.Web.UI.Page {
public Object SomeMethod() {
return Cache["SomeObject"];
}
}
is fine. As it's sealed, what you can't do is this:
public class MyClass : Cache {
// override or add some methods here
}
I stumbled into this problem. The comment is correct The Cache class is a sealed class, which means it cannot be inherited. Since you are inheriting the Page class in your X testClass the Cache object will not be available. One way to solve the problem is to pass the Cache object of the Page to the Method that need to process the Cache information as shown in the Sample code..
<%@ import Namespace="Env" %>
<%@ import Namespace="System.Xml" %>
<%@ Page Language="C#" Inherits ="Env.ServerProcess" %>
<%
XmlDocument xDoc = new XmlDocument();
xDoc=ProcessRequest(Request.InputStream,this.Cache);
Response.ContentType="text/xml";
Response.Write (xDoc.OuterXml);
%>
public class ServerProcess : System.Web.UI.Page
{
public XmlDocument ProcessRequest(Stream PageRequestStream,Cache MyCache)
{
string sResetClientId="";
XmlDocument xdoc =new XmlDocument();
try{
if (MyCache ["ResetClientDoc"] == null){
TextReader xt=new StreamReader(Server.MapPath(@"Content/ResetClientID.xml"));
sResetClientId=xt.ReadToEnd();
xt.Close();
MyCache dep = new CacheDependency(Server.MapPath(@"Content/ResetClientID.xml"), DateTime.Now);
MyCache.Insert("ResetClientDoc", sResetClientId, dep);}
Else
{
sResetClientId=(string) MyCache ["ResetClientDoc"];
}
}
catch (Exception e){
System.Diagnostics.Debug.WriteLine( e.Message.ToString())
}
xdoc.LoadXml(sResetClientId);
return xdoc;
}
Hi Charlie,
You can use .NET remoting when you need to keep your cache across processes. The process is discussed here Using Remoting Singleton Caching.
Hope this helps.
-DM
As for caching across processes, you'll need to use .NET remoting. The process is discussed here The process is discussed here Using Remoting Singleton Caching.
Hope this helps.
-DM
Yes I have tried that as well. IMHO: The thing is that you are trying to access a cache object from a class. But the documentation says that the Cache object cannot be inherited. therefore I would expect it to throw a "Cache is not available" exception. Now this is a real bugger specially when you want to cache data across process/pages. This is precisely what I'm trying to do right now and I have yet to find a solution. Help anyone?
How would one use the .NET cache object to keep caches accurate across processes?
--Charlie
On what line does the error occur?
// test.cs
//
namespace xtest {
using System;
using System.Web;
using System.Web.Caching;
public class xtest {
public static Cache srvCache = new Cache();
public xtest() {}
public static string getCache(string key){
try {
object strServer= 0;
if (srvCache["ServerString"] == null)
srvCache["ServerString"]=key;
strServer = srvCache.Get("ServerString");
return (string) strServer;
}
catch (Exception e)
{
return "error: getCache() - "+ e.Message;
}
}
}
}
When I run the below mentioned aspx. I get error:
- Object reference not set to an instance of an object.
<%@ Page Language="C#" %>
<%@ import Namespace="xtest" %>
<script runat="server">
void Page_Load(object sender, EventArgs e) {
Response.Write(xtest.getCache("X-STAGE"));
}
</script>
<html>
<head>
</head>
<body>
<form runat="server">
<!-- Insert content here -->
</form>
</body>
</html>
This thread is for discussions of .NET Data Caching.