locked
Using cache in a web service RRS feed

  • Question

  • User-755538356 posted

    I have inherited a asmx web service that makes numerous database calls but doesn't cache any of the results.  Thus, each call to the web service hits the database.  I'd like to implement the use of caching to reduce the number of such calls and hopefully, improve overall performance.  Unfortunately, I've never used (or written) any type of caching logic.  Thus, I have several questions as follows:

    1) How do I go about implementing cache logic in the web service?  I presume I should write a separate class but that is just a presumption as I've seen some examples which had cache logic written directly in a web method.  So, I'm looking for what would be the best practice for implementing cache logic into a web service.

    2) One of the database queries checks for the existence of an  item and returns true if the item exists in the database. Otherwise, false is returned.  Would it be better to store the results of such a query in a dictionary (i.e. dictionary<string, boolean>) then cache the dictionary or could I simply use the item as the cache key and have the value be the boolean?  I like the idea of the latter because it seems easier but there could possibly be several thousand items resulting in several thousand cache keys.  Is that acceptable or would having so many cache keys cause issues?  I'm thinking not but haven't been able to find a definitive answer or whether this would go against best practices. 

    3) Related to 2, if I need to use a dictionary, how could I add new items to the dictionary safely (i.e. how do I update cache in a thread safe manner)?  I've seen lots of postings showing how to read from cache or add a new value to it but not how to safely update an existing value.  

    While I am sure I'll have more questions as I go along, hopefully, answers to the above will get me started down the right path.  Also, any examples, links, etc. are appreciated.

    Thank you.

    Monday, June 4, 2018 11:07 AM

Answers

  • User475983607 posted

    I have inherited a asmx web service that makes numerous database calls but doesn't cache any of the results.  Thus, each call to the web service hits the database.  I'd like to implement the use of caching to reduce the number of such calls and hopefully, improve overall performance.  Unfortunately, I've never used (or written) any type of caching logic.  Thus, I have several questions as follows:

    See output caching

    https://support.microsoft.com/en-us/help/318299/how-to-perform-output-caching-with-web-services-in-visual-c-net

    And/or distributed cache before rolling your own.

    https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed?view=aspnetcore-2.1

    And this is a problem because your DB does not change much?  Because the queries are long running?  Keep in mind that adding cache that's local to the ASMX service negatively impacts the ability to "scale out".  Plus, it introduces a margin of data error as cached data might not be synced with data persisted in the DB.  

    1) How do I go about implementing cache logic in the web service?  I presume I should write a separate class but that is just a presumption as I've seen some examples which had cache logic written directly in a web method.  So, I'm looking for what would be the best practice for implementing cache logic into a web service.

    If you wish to roll your own, the use memory cache that contains a dictionary.  The dictionary key being the method and input parameters.

    https://msdn.microsoft.com/en-us/library/system.runtime.caching.memorycache(v=vs.110).aspx

    2) One of the database queries checks for the existence of an  item and returns true if the item exists in the database. Otherwise, false is returned.  Would it be better to store the results of such a query in a dictionary (i.e. dictionary<string, boolean>) then cache the dictionary or could I simply use the item as the cache key and have the value be the boolean?  I like the idea of the latter because it seems easier but there could possibly be several thousand items resulting in several thousand cache keys.  Is that acceptable or would having so many cache keys cause issues?  I'm thinking not but haven't been able to find a definitive answer or whether this would go against best practices. 

    Like above, I would use input parameters and the method name to key the dictionary.  First, make sure this approach is beneficial.  How long does it take to execute this query?  

    3) Related to 2, if I need to use a dictionary, how could I add new items to the dictionary safely (i.e. how do I update cache in a thread safe manner)?  I've seen lots of postings showing how to read from cache or add a new value to it but not how to safely update an existing value

    Use locks.

    https://stackoverflow.com/questions/21269170/locking-pattern-for-proper-use-of-net-memorycache?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa

    Keep in mind, locks serialize access which limits not only scalability but performance.  Meaning the requests become synchronous as apposed to asynchronous.  I  assume you're going down this path because the data does not change much. 

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, June 4, 2018 11:32 AM

All replies

  • User475983607 posted

    I have inherited a asmx web service that makes numerous database calls but doesn't cache any of the results.  Thus, each call to the web service hits the database.  I'd like to implement the use of caching to reduce the number of such calls and hopefully, improve overall performance.  Unfortunately, I've never used (or written) any type of caching logic.  Thus, I have several questions as follows:

    See output caching

    https://support.microsoft.com/en-us/help/318299/how-to-perform-output-caching-with-web-services-in-visual-c-net

    And/or distributed cache before rolling your own.

    https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed?view=aspnetcore-2.1

    And this is a problem because your DB does not change much?  Because the queries are long running?  Keep in mind that adding cache that's local to the ASMX service negatively impacts the ability to "scale out".  Plus, it introduces a margin of data error as cached data might not be synced with data persisted in the DB.  

    1) How do I go about implementing cache logic in the web service?  I presume I should write a separate class but that is just a presumption as I've seen some examples which had cache logic written directly in a web method.  So, I'm looking for what would be the best practice for implementing cache logic into a web service.

    If you wish to roll your own, the use memory cache that contains a dictionary.  The dictionary key being the method and input parameters.

    https://msdn.microsoft.com/en-us/library/system.runtime.caching.memorycache(v=vs.110).aspx

    2) One of the database queries checks for the existence of an  item and returns true if the item exists in the database. Otherwise, false is returned.  Would it be better to store the results of such a query in a dictionary (i.e. dictionary<string, boolean>) then cache the dictionary or could I simply use the item as the cache key and have the value be the boolean?  I like the idea of the latter because it seems easier but there could possibly be several thousand items resulting in several thousand cache keys.  Is that acceptable or would having so many cache keys cause issues?  I'm thinking not but haven't been able to find a definitive answer or whether this would go against best practices. 

    Like above, I would use input parameters and the method name to key the dictionary.  First, make sure this approach is beneficial.  How long does it take to execute this query?  

    3) Related to 2, if I need to use a dictionary, how could I add new items to the dictionary safely (i.e. how do I update cache in a thread safe manner)?  I've seen lots of postings showing how to read from cache or add a new value to it but not how to safely update an existing value

    Use locks.

    https://stackoverflow.com/questions/21269170/locking-pattern-for-proper-use-of-net-memorycache?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa

    Keep in mind, locks serialize access which limits not only scalability but performance.  Meaning the requests become synchronous as apposed to asynchronous.  I  assume you're going down this path because the data does not change much. 

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, June 4, 2018 11:32 AM
  • User-755538356 posted

    mgebhard,

    Thank you so much for the detailed response.   I think this will get me started down the right path.  Much appreciated!

    Monday, June 4, 2018 7:29 PM