Click here to Skip to main content
16,021,687 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am working on an application where i intend to load requested data and cache the items for subsequent requests to the same item.

If the item isn't in the cache i intend to make a database call and cache the desired items into a collection for later use.

This is the Product entity:
ProductID
ProductName
ProductType
ProductPrice



I am using ODP.NET and C# to load the records.

Currently i can load all the products by invoking:
C#
dbProvider.GetAllProducts();


But this is obviously not a good idea for filtering the products so i have created a method to load the products in one or more ways: By List of ProductID, List of ProductName and/or List of ProductTypes.

This is because the end user will be providing a List which can be either be
List of ProductIDs And/Or List of ProductNames And/Or List of ProductTypes.

I want to filter the cache using the List of ProductsIDs and/Or List of ProductNames and/or List of ProductTypes.

What I have tried:

As i am using the repository pattern i extended my ProductsRepository to load the filtered products:

C#
IEnumerable<productdao> loadedProducts = dbProvider.GetFilteredProducts(List<int>ProductIDs, 
                               List<string>ProductNames, 
                               List<string>ProductTypes);



i have started to write the code to cache but i am having issues with implementing what i want to achieve.

C#
//Get the default MemoryCache to cache objects in memory
  ObjectCache cache = MemoryCache.Default;
 
  CacheItemPolicy policy = new CacheItemPolicy();
  policy.AbsoluteExpiration = DateTimeOffset.Now.AddMinute(120.0);
 
   //check if data exists in cache
   //Get data from the database and cache them
   IEnumerable<product> loadedProducts  dbProvider.GetFilteredProducts(List<int>ProductIDs, 
                               List<string>ProductNames, 
                               List<string>ProductTypes);
           ...
   //loop through them all and add to cache so user can access them in 3 ways
   //cache.Add("Product" + id, result, policy);


Once i have cached the items I want to use it in my ProductBusinessLogic class to filter the cache using the List of parameters the user has provided. Is this possible?

How would i check the cache based on what the user has provided e.gList of ProductIds or List of ProductTypes or List of ProductNames.

How would i store the loaded Products from the database into the cache correctly, knowing that the user can request to access the data based on 3 particular ways?
Posted
Updated 18-Nov-16 1:20am
v3

1 solution

There are two approaches you could take. One is that you simply cache all products and every time someone calls GetFilteredProducts you get the list of all products from the cache then do the Where on it. That way you only need to worry about caching all the products, but the downsides are that the filtering happens every time someone does a request. If there aren't many products this is probably the better way to go as it is simple and chances are the retrieval of the products takes more CPU time than the filtering.

The second approach is to cache the results of their query so that when another query with the same params come in you simply get it from the cache. To do this you need to generate a clever key to use as the cache key. So let’s say someone searches for product IDs 100, 107, 102, 106…to generate a key from that order the IDs;

100, 102, 106, 107

Then turn that into a string like

“100_102_106_107”

And that is your cache key. So when someone searches for product IDs 100, 101 the cache key for that is “100_101”. When someone else searches for 107, 106, 100, 102 then the cache key for that is “100_102_106_107” which matches the first search so the results are got from the cache. You’ll need to extend this concept for all of your params so for names the key would be something like “ProductA_ProductB” and so on. If you can search for IDs and names then the key will be “100_101_ProductA_ProductB” etc.

If you are searching on a lot of things the key will get very large, so once you have your string, get the hash value of it using GetHashCode().ToString() (I think that’s what it’s called) and use the hash as the cache key instead.

The good thing about this approach is that it is the best performing, if a search has been done before you get instant results. The downsides are if the queries are varied and many. If people are always searching for different things then you’ll end up with a lot of cached data and very few successful hits on the cache. Using this technique you’re best to use a sliding expiration so un-wanted queries drop out the cache.

You can also combine both techniques. Always cache the products so if you get no hit on the parameter caching and you have to generate a new query you run that query on the cached version of the products.

So it’s up to you to decide what strategy is best given your data size and the types of queries you think people are going to do.
 
Share this answer
 
Comments
Eagle32 19-Nov-16 11:20am    
Thanks for the response. Yeah i see what you mean, the end users can provide various combinations so i will need to look deeper into your suggestions etc.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900