views:

75

answers:

5

Hi, I have a function which calculates distance from database records. This function is called at least twice in one asp.net page request. In this time period the result does not change. So what to do to cache result, I need performance in my app.

For example:

public static int GetKilometers(int VehicleID)
{ /*some db query and calculations*/ }
A: 

save in session with an if-condition if it definitely doesn't change

if(Session["functionresult"] == null)
{
    Session["functionresult"] = functionResult;
}
David
I dont thing its a good idea to store large data in session. Also there is no only one value. There could be 50~1000 of them.
HasanGursoy
+1  A: 

For a quick and easy solution, you can use the HttpContext.Session object to store a value like this:

int distance;
if(Session["distance"] == null)
{
    distance = GetKilometers(vehicleId);
    Session["distance"] = distance;
}
else
{
    distance = Convert.ToInt32(Session["distance"]);
}

To make it even easier, you can abstract this into its own method.

EDIT

The above solution is good for a minimal amount of data. Given the fact that there will be a LOT of data being stored in your case, I see two possible scenarios:

The calculated data for a vehicle X is different for each user
Cache the calculated data in a separate table in the database with UserId (or SessionId), VehicleId, and CalculatedData.

The calculated data for vehicle X is the same for any user that needs vehicle X's data
Cache that calculated data in a column in the vehicle table in the database.

Either way, your call to the database should retrieve data for all vehicles that the user needs for the current request. Then store that data in a local variable that lives only for the current request. If you're going to cache data by session, you can use HttpContext.Session to store the SessionId and use that to retrieve the data from the database.

Aaron
There could be 6000 vehicles and 500 users.A user can query all of his vehicles within a week for example.
HasanGursoy
If you're worried about memory management, then you could easily implement a session that is stored in the database. In this case, you might store a sessionId in HttpContext.Session and retrieve session data from the database in a single query instead of multiple queries throughout the lifecycle of the request. This way, only a minimal amount of data would be left in memory.
Aaron
So you are saying that this function could be called 6000 times for a single page?
Lazarus
If this function *will* get called 6000 times for a single page (once per vehicle), then it would be a good idea use a database procedure that will return ALL of the distances into a list (or even a dictionary with the vehicle IDs as the key).
Aaron
No, the function can call 10 to 100 vehicles per page request/ajax request. But it takes 5-10 seconds to process
HasanGursoy
"The calculated data for vehicle X is the same for any user that needs vehicle X's data" this is my scenario. Probably the best solution is to store calculated data in another table.
HasanGursoy
A: 

If there are that many calculations, than using Session will eat up your server memory. You could use ViewState, but that would make your page pretty heavy.

Is it possible not to hit the db? Or minimize the number of round trips to the db.

Something like:

public static int GetKilometers(int[] VehicleID) { /* get all the data in one go */ }

Steve
Maybe I can save result to another table in MySql.I have location data coming each minute from a vehicle.I'm calculating the hypotenuse between Longtitude and Lattitude data and then I return sum of this data.Also I'm calling my data with ajax
HasanGursoy
Yes that would work. In addition to the caching, I would try and get the results all at once, rather than calling a function x times that each making a db request (assuming that's how it works now) Send all the vehicle IDs to the database in one go and send back all the mileages at once. This way you're making 1 db connection rather than x connections. I think the db hit is what you should be looking at.
Steve
+2  A: 

If you're only concerned about the result in the lifetime of one page request (as you mention in your question), a simple local variable will suffice:

private int? _dist;

public int GetKilometers(int VehicleID)
{ 
    if (_dist == null) {
        _dist = /*some db query and calculations*/ 
    }
    return _dist;
}

This would prevent any memory concerns from excessive caching, but still allow some efficiency by not calculating the data twice for the same request.

One note is that you probably don't want this static, as that will cache the result across multiple users of your application.

Ryan Brunner
Yeah... what Ryan said while I was typing my answer! ;) (+1)
Lazarus
+1  A: 

From the OP's question all of these answers are useful and the syntax is the same but the wrong collections are being used. The proper collection for this is HttpContext.Current.Items. Combine this with the answer from @Aaron

Chris Marisic