I wanted to know if there is any event which occurs each time a cache item is about too get expired or any event which is raised when a cache item is getting expired.I am using enterprise library in asp.net for caching.I want to store some data in my database when a cache is about to get expired instead of calling a function or invoking an event myself I was thinking of using the already managed cache library event which is being used to flush or dispose cache items.
Assuming you're using the Caching Application Block then you specify a callback delegate when you add items to the cache.
Receiving notification of an item's removal from the cache requires that you specify the class implementing ICacheItemRefreshAction on the call to the Add method
You need to supply a class implementing ICacheItemRefreshAction:
[Serializable]
public class ProductCacheRefreshAction : ICacheItemRefreshAction
{
public void Refresh(string key, object expiredValue, CacheItemRemovedReason removalReason)
{
// Item has been removed from cache. Perform desired actions here, based on
// the removal reason (for example, refresh the cache with the item).
}
}
As you can see, when an item is removed, this Refresh() method is called with the key and the object that's being removed. You just need to cast the expiredObject parameter to the correct type and arrange to have it stored to the database.
As documented here: http://msdn.microsoft.com/en-us/library/ff664621(v=PandP.50).aspx
Related
I want refresh a form from a class. I want the refreh after a insert() statemant. Is here a better solution for this problem.
Here is my code:
try {
do {
row++;
this.readRow(row, cells);
ttsbegin;
this.insert();
ttscommit;
type = cells.item(row+1, 1).value().variantType();
}
while (type != COMVariantType::VT_EMPTY);
<--------
After the while the insert is finished and at this position where I will the refresh.
Usually you would pass a reference of the form's data source you want to refresh to your class and then call research on it to refresh it so that your newly inserted records appear.
Alternatively, although IMHO not that clean, is to pass a buffer of that form's data source to your class and then (maybe after checking via isFormDataSource) access and refresh the data source via the buffer's dataSource method.
A third way would be to implement a dedicated method on your form solely for the purpose of refreshing the data source as described above. When creating the instance of your class you then pass a reference to your form so that you can call that method when needed.
Update: To see how to call a method defined on a form from a class see the class Tutorial_Apply and form Tutorial_Form_Apply which shows how to call the method applyText which is implemented on the form. Likewise, you could define a method refreshData which calls research on your data source.
I just discovered System.Web.Caching.Cache used in a project that I am working on and I am having a hard time finding more information on it.
My question is how this cache is persisted? Is it client-side (similar to ViewState), server-side (Session)? Entirely different?
Example:
protected string FileContent
{
get
{
return Cache[FILE_UPLOAD_KEY + Id] as string ?? GetFileUpload();
}
}
It's a server-side, application-wide cache.
One instance of this class is created per application domain, and it
remains valid as long as the application domain remains active.
Information about an instance of this class is available through the
Cache property of the HttpContext object or the Cache property of the
Page object. (Cache Class, MSDN)
It grants the ability to set time limits and so forth on cached objects. And it doesn't promise the object will be there when you need it again. It keeps items in cache only so long as there is sufficient memory to do so.
So, it's not intended for passing objects between page views (use ViewState or Session for that) or controls (use Items for that). It's intended to cache global objects (accessible in any request from all clients) that are expensive to build.
It's persisted at the server, and it's global across sessions, like Application. So when you set a value in the Cache, it's available to all users until it expires.
EDIT
The example you've got probably isn't quite right (unless GetFileUpload() actually writes to the cache). Generally your calls to cache look something like:
string GetSomeStringFromCache()
{
string someString = Cache[SomeKey] as string;
if (someString == null)
{
someString = GetStringUsingSomeExpensiveFunction();
Cache.Add(SomeKey, someString, /*a bunch of other parameters*/);
}
return someString;
}
This will put it in the Cache if it's not already there, but if it is, it will just use it.
Say I have a page in my web application that lets a user update their contact information. Pretend in order to retrieve or save this information I have the following class:
public class User
{
DataAccesClass dataAccesClass = new DataAccesClass()
public string UserName {get;set;}
public string Address {get;set;}
public string EmailAddress {get;set;}
public User(){}
public static User GetUser(int userID)
{
User user = dataAccesClass.GetUser(userID); //
return user;
}
public void Save()
{
dataAccesClass.SaveUser(this);
}
}
Say that on my Page_Load event I create a new instance of my User class (wrapped in a !isPostBack). I then use it's public properties to populate text fields on said page in my web application. Now the question is... When the page is posted back, what is the correct way to rebuild this class to then save the updated information? Because the class was created on Page_Load !isPostBack event it is not available. What is the correct way to handle this? Should I store it in a Session? ViewState? Should I simply rebuild it every post back? The User class in this example is small so that might influence the correct way to do it but I'd like to be able to take the same approach for much larger and more complex classes. Also, would this class be considered an acceptable business object?
what is the correct way to rebuild this class to then save the updated information?
I would say the best practice would be do not rebuild the class on every postback. You should build the data on the first request, set values on controls, then let the viewstate on those controls persist the data.
If there is a potential for the data to need to be updated, tie re-generation of the object to an event indicating there is actual need to update.
Should I store it in a Session? ViewState? Should I simply rebuild it every post back?
Selecting whether to store the value in session or re-pull from the data layer should be based on the memory footprint of the object, the scalability requirements of the application, the costliness of the database operation, and the likelihood that the object will need to be accessed on any particular request. So I believe that is highly situational.
Also, would this class be considered an acceptable business object?
I don't have a lot of experience with BLL's but it looks like you're on the right track.
Unless profiling indicates otherwise, it's okay to just reconstruct the object with every request. You can also implement some kind of caching in your data access code. Your class is an acceptable business object.
Given that User object might have info you wouldn't want to expose through ViewState, it can be stored in Session.
This is the "standard" way of doing this in ASP.NET.
In the case of your example, reconstructing the object looks fine as it is small. But if you have a small object you inevitably store for a while, I would use session. If the object is large, I would directly use database or session with database connection.
Depending how complex you are thinking of getting a JavaScript framework called knockout.js might be a good fit. You could create a json object to bind to a jQuery template that would build the HTML depending on the object, it handles complex objects very well.
I am fixing an ASP.NET application that makes heavy use of session to track per-page data. One of the problems is that the session bleeds between pages.
ViewState would be a better solution, except:
The data is not serializable
There is too much data to be sending back and forth each postback
So I want to:
create a page key for the session data (i.e. stick a random GUID in a hidden field)
expire data from an abandoned page even if the overall session is active
Is there a good way to expire partial session data?
The following temporary storage locations are available:
Session. This follows a user around and uses a cookie. It can be configured to use a URL param to retrieve. Session can also be configured to be stored in process(inproc) on the web server, in SQL Server, or in a state server. InProc can store any data type, but the others require the type to be serializable.
Cache. Data stored in Cache is available to be used by any user in an session. It works similar to session, as the objects are retrievable via a key. One of the nicer features of cache is that you can control how long things are stored, and you can consume event when they expire. You can store anything here, but you may run into issues with using it in a webfarm.
HttpContext. This is scoped to the current request. Remember, requests can be webservice calls, calls to get webpages to get HTML, or calls to a service that returns images. Anything can be stored here.
ViewState. View state is scoped to a page. Must be serializable.
You may want to examine cache. If you're using a webfarm, it won't work, but you could use a GUID of some sort as the key that you map back to a session.
I would probably do it this way:
Create an object to store the state information you want to be page specific. If different pages need different information, create multiple classes.
Store this object in a single session key: Session["PageSpecific"]; for example.
Create a class which inherits from System.Web.UI.Page.
In the OnLoad event of the base class, clear the session key if the the page is not performing a postback.
Create and call an overloadable method to populate the session object.
Instead of inheriting from System.Web.UI.Page in each of your pages, inherit from your new base class.
Something like this (warning: air code. May contain syntax errors):
public class PageBase
: System.Web.UI.Page
{
protected overrides OnInit(System.EventArgs e) {
base.OnInit(e);
if(!this.IsPostBack) {
Guid requestToken = System.Guid.NewGuid();
ViewState["RequestToken"] = requestToken;
Session["PageSpecific" & requestToken.ToString()] = InitializePageSpecificState();
}
}
protected virtual object InitializePageSpecificState() {
return new GenericPageState();
}
//You can use generics to strongly type this, if you want to.
protected object PageSpecificState {
get {
return Session["PageSpecific" & ViewState["RequestToken"].ToString()];
}
}
}
Perhaps on each page !IsPostBack or through a base page you could null out all references to session data not pertaining to that page. This would "expire" the data each time the user goes to another page in the site.
If the user leaves the site or goes in-active, there's not much you can do until the session expires, but in this scenario there would only be one page worth of session data per user.
The background to this question is that I need to use some user session data in a (static) WebMethod. I have created a static property that references the data I need like so:
private static UserWebSession UserWebSession
{
get
{
return (UserWebSession)HttpContext.Current.Session["UserWebSession"];
}
}
I can then call this in my page's static WebMethod.
My question is, is this technique thread safe? Or will this property's value be updated with every new page request - in other words, it will return the UserWebSession for the user who most recently requested the page?
That's fine - HttpContext.Current is designed precisely for this sort of thing. You won't get a previous user's session.
It's dependent on the thread though (I believe) - so if you start any extra background threads, they won't be able to see the current context.
Also be aware that although this call is safe in terms of not getting the wrong context, the normal concurrency caveats apply when it comes to what you actually do with the context.
I don't know that a Page Method is able to access Session state. If it can, then you may be ok. I recall that access to Session state is serialized, so that only one request at a time can arrive for a given session.