I need to implement caching in Asp.net web application
My need to store data with different ID's.
So which method is better ?
Use a dictionary variable. Insert the data (key as ID and data as value).
Dim mDict As New Dictionary(Of String, String)
mDict .Add(bID, uwtTree.WriteXmlString(True, True))
Cache.Insert("mTree", mDict)
Add it to a cache variable.
Access the cache variable
If Not Cache("mTree") is Nothing Then
'cast to dictionary and check ID exists , if exsitis get the data
End iF
Use cache variable for different IDs
Cache.Insert(ID,data)
' each insertion for each ID
If Not Cache(ID) is Nothing Then
' get the data. '
End IF
Which method is the best way ? Or is there any other method exists ?
I am using .Net 3.5 /IIS 7 (VB.Net). Thanks in advance
Way to Improve Performance and Memory Optimization
Without context it's not possible to say which is "better".
But if you put a dictionary in the cache (option 1), better make sure it's a thread-safe dictionary (such as the .NET 4 ConcurrentDictionary).
The most obvious difference between the two approaches is that with option 1, cache item expiry will result in the dictionary with all items being removed at once. With option 2, individual items will expire independently.
In response to the comment:
i am having xml data and i will store in cache (data caching) as string. Is there any difference if i store it as XmlObject ?
The main differences I see are:
String is immutable, so you won't need to worry about thread-safety when accessing it. XML objects are not immutable - so you need to make sure you don't modify the object retrieved from the cache (or use locks to make sure any such modification is thread-safe).
If you store a string, you will presumably parse it into an XML object each time you retrieve it from the cache, which will result in a potential performance penalty.
Related
What is the difference between the Cache.Add() and Cache.Insert() methods?
In which situations should I use each one?
Insert will overwrite an existing cached value with the same Key; Add fails (does nothing) if there is an existing cached value with the same key. So there's a case for saying you should always use Insert since the first time the code runs it will put your object into the cache and when it runs subsequently it will update the cached value.
Cache.Add() also returns a cached object from Cache after it was added:
string cachedItem = Cache.Add("cachedItem", ....);
You can use either Cache.Add() or Cache.Insert() methods for caching your data. The only difference between the two is, Cache.Add() method returns the object which you want to cache.
So let’s say if you want to use the object and cache it as well. You can do so in a single line of code with the help of Cache.Add().
Cache.Insert() methods has 4 different types of overloaded methods while Cache.Add() has only one.
I have an ASP.NET c# project.
I have to pass a list of values (id numbers such as "23,4455,21,2,765,...) from one form to another. Since QueryString is not possible because the list could be long, which is the best way to do it?
Thanks in advance.
Thanks for all your answers, you are helping a lot !!!
I decided to do this:
On the first form:
List lRecipients = new List();
.....
Session["Recipients"] = lRecipients;
On the final form:
List lRecipients = (List)Session["Recipients"];
Session.Remove("Recipients");
You could use Session collection.
In the first page, use:
List<int> listOfInts = new List<int>();
...
Session["someKey"] = listOfInts
And in the second page, retrieve it like this:
List<int> listOfInts = Session["someKey"] as List<int>;
If your using asp.net webforms you can put it into a session variable to pass stuff from page to page. You've got to be concise of the potential performance issues of putting lots of stuff into session mind.
Session["ListOfStff"] = "15,25,44.etc";
There are any number of ways to pass this data. Which you choose will depend on your environment.
Session state is useful, but is constrained by the number of concurrent users on the system and the amount of available memory on the server. Consider this when deciding whether or not to use Session state. If you do choose session state for this operation, be sure to remove the data when you're done processing the request.
You could use a hidden input field, with runat="server" applied to it. This will make its data available server-side, and it will only last for the duration of the request. The pros of this technique are that it's accessible to both the server code and the client-side JavaScript. However, it also means that the size of your request is increased, and it may take more work to get the data where you want it (and back out).
Depending on how much data's involved, you could implement a web service to serialize the data to a temporary storage medium (say, a database table), and get back a "request handle." Then, you could pass the request handle on the query string to the next form and it could use the "handle" to fetch the data from your medium.
There are all kinds of different ways to deal with this scenario, but the best choice will depend on your environment, time to develop, and costs.
For Asp.NET MVC you can use ViewData.
ViewData["ID"] = "";
I'm writing a webcontrol in asp.net which has to go and fetch information from an API. It's not critical to be up-to-date, and retrieving the information is quite slow, so I'd rather cache the information and update it every 5 minutes.
It strikes me as potentially risky to use the Context.Cache as potentially someone could use the same name, but I can't find another way to do caching within a control.
Does anyone have any other ideas?
(using asp.net 2.0).
It sounds like the Context.Cache is exactly what you need to store this kind of information. The cache object is localized to your application so it would only be changeable by other code in your application.
You can always give your cache key a very long and presumably useless name etc and store that key within your class...
Private const CacheKey as String = "e92a627b-3a9f-46da-a182-d73b44fe87ad" ' A random guid
Cache.Item(CacheKey) = TheRefreshedData ' etc
As I was writing this answer I realised maybe you were talking about your conntrol being re-used within someone else's application...as in your control is redistributed or provided for download. In this case, you could always prefix the cache key with your control to be "sensibly" unique...
Private const CacheKey As String = "MyCompany.MyControl.MyData"
Cache.Item(CacheKey) = TheRefreshedData ' etc
Either way, you should be able to come up with some fairly length string that has zero chance of being reused...
I am debugging an application that uses an XML file to store data as key/value pairs.
Every pageload the XML file is parsed to populate a Dictionary collection with these key/value pairs. The Dictionary is then used to look up values based on their keys.
Is this method of loading data from an XML file on every page load a good practice?
Here are some thoughts:
Should the XML data be stored in a database table instead?
Should I work with a collection or hit the database for every lookup request?
Could the collection be loaded on application start and set as a global/application property?
What do you guys think?
I would suggest loading the results of the XML Parsing into the ASP.NET Cache:
Dictionary<string, object> values = new Dictionary<string, object>();
if(Cache["ConfigDictionary"] != null)
{
values = (Dictionary<string, object>)Cache["ConfigDictionary"];
}
else
{
// Load data into the dictionary here
// This dependency will ensure that you don't keep stale data in the cache
CacheDependency dependency =
new CacheDependency(Server.MapPath("yourFileHere.xml"));
// Inser the Dictionary into the cache
Cache.Insert("ConfigDictionary", values, dependency);
}
I agree with #Justin, keeping the collection into cache is nice.
Also, the question about storing data in a database, depends mostly on what content the app is loading. If there is config settings, or another data that has low probability to change, I think is more efficient keeping it in a XML file. Why?
Easier to maintain;
You dont need to care about connections, queries, parameters;
Easier to view data content;
Non database-skilled people (support for app), can change settings.
I would store it in the database instead of XML file. It is easier to query (if you have to run some reports for example) and also backup is sort of more controllable.
Of course, I assume you are using database for your web application in general.
You may try to use Viewstate to decrease number of database runs if your are in the context of the same web page.
I have object A which in turn has a property of type Object B
Class A
property x as Object B
End Class
On my ASP.NET page when I select a gridview item which maps to an object of type A I serialize the object onto the QueryString and pass it to the next page.
However I run into problems if property x actually has some value as it looks like I exceed the QueryString capacity length of 4k (although I didn't think the objects were that large)
I have already considered the following approaches to do this
Session Variables
Approach not used as I have read that this is bad practice.
Using a unique key for the object and retrieving it on the next page.
Approach not used as the objects do not map to a single instance in a table, they arte composed of data from different databases.
So I guess my question is two fold
Is it worth using GKZip to compress the querystring further (is this possible??)
What other methods would people suggest to do this?
If displaying the url of the next page in the browser does not matter, you could use the context.items collection.
context.items.add("keyA", objectA)
server.transfer("nextPage.aspx")
Then on the next page:
public sub page_load(...)
dim objectA as A = ctype(context.items("keyA"), objectA)
dim objectB as B = objectA.B
end sub
One reason to use this is if you want the users to believe that the next page is really a part of the first page. To them, it only appears as if a PostBack has occurred.
Also, you don't really need a unique key using this approach if the only way to use "next page" is if you first came from "first page". The scope for the context items collections is specific to just this particular request.
I agree with the other posters who mentioned that serialized objects on the querystring is a much worse evil than using session state. If you do use session state, just remember to clear the key you use immediately after using it.
I don't understand why you wouldn't use session state but...
Option 1: Viewstate
Option 2: Form parameters instead of querystring
But also be aware that you do not get the same object back when you serialize/deserialize. You get a new object initialized with the values of the original that were serialized out. You're going to end up with two of the object.
EDIT: You can store values in viewstate using the same syntax as Session state
ViewState["key"] = val;
The value has to be serializeable though.
While storing objects in session might be considered bad practice, it's lightyears better than passing them via serialized querystrings.
Back in classic asp, storing objects in session was considered bad practice because you created thread-affinity, and you also limited your ability to scale the site by adding other web servers. This is no longer a problem with asp.net (as long as you use an external stateserver).
There are other reasons to avoid session variables, but in your case I think that's the way to go.
Another option is to combine the 2 pages that need access to this object into one page, using panels to hide and display the needed "sub-pages" and use viewstate to store the object.
I don't think passing it in the query string, or storing it in the session, is a good idea.
You need one of the following:
a) A caching layer. Something like Microsoft Velocity would work, but I doubt you need something on that scale.
b) Put the keys to each object in the databases that you need in the query string and retrieve them the next time around. (E.g. myurl.com/mypage.aspx?db1objectkey=123&db2objectkey=345&db3objectkey=456)
Using session state seems like the most practical way to do this, its exactly what its designed for.
Cache is probably not the answer here either. As Telos mentioned, I'm not sure why you're not considering session.
If you have a page that depends on this data being available, then you just throw a guard clause in the page load...
public void Page_Load()
{
if(!IsPostBack)
{
const string key = "FunkyObject";
if(Session[key] == null)
Response.Redirect("firstStep.aspx");
var obj = (FunkyObject)Session[key];
DoSomething(obj);
}
}
If session is absolutely out of the quesiton, then you'll have to re-materialize this object on the other page. Just send the unique identifier in the querystring so you can pull it back again.
Session isn't always available. For instance when XSS (cross-site-scripting) security settings on IE prevent the storage of third-party cookies. If your site is being called within an IFrame from a site that's not your DNS domain, your cookies are going to be blocked by default. No cookies = no session.
Another example is where you have to pass control to another website that will make the callback to your site as a pure URL, not a post. In this case you have to store your session parameters in a querystring parameter, something that's tough to do given the 4k size constraint and URL encoding, not to mention encryption, etc.
The issue is that most of the built-in serialisation methods are pretty verbose, thus one has to resort to a roll-your-own method, probably using reflection.
Another reason for not using sessions is simply to give a better user experience; sessions get cleared after N minutes and when the server restarts. OK, in this case a viewstate is preferable, but sometimes it's not possible to use a form. OK, one could rely on JavaScript to do a postback, but again, that's not always possible.
These are the problems I'm currently coding around.
Here is what I do:
Page1.aspx - Add a public property of an instance of my object. Add a button (Button1) with the PostBackURL property set to ~/Page2.aspx
Private _RP as ReportParameters
Public ReadOnly Property ReportParams() as ReportParameters
Get
Return _RP
End Get
End Property
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
_RP = New ReportParameters
_RP.Name = "Report 1"
_RP.Param = "42"
End Sub
Now, on the second page, Page2.aspx add the following to the Markup at the top of the page under the first directive:
<%# PreviousPageType VirtualPath="~/Default.aspx" %>
Then for the Page_Load in the code behind for Page2.aspx, add the following
If Not Page.PreviousPage is Nothing Then
Response.write (PreviousPage.ReportParams.Name & " " & PreviousPage.ReportParams.Param)
End If
Faced with a similar situation what I did, is to XML serialize the object and pass it around as query string parameter. The difficulty with this approach was that despite encoding, the receiving form throws exception saying "potentially dangerous request...". The way I got around was to encrypt the serialized object and then encode to pass it around as query string parameter. Which in turn made the query string tamper proof (bonus wandering into the HMAC territory)!
FormA XML serializes an object > encrypts the serialized string > encode > pass as query string to FormB FormB decrypts the query parameter value (as request.querystring decodes also) > deserialize the resulting XML string to object using XmlSerializer.
I can share my VB.NET code upon request to howIdidit-at-applecart-dot-net