0

We have a static List of Foo. I'm trying to make sure that, if a Foo doesn't exist, grab it from the db. This operation (the DB-Get) is expensive so I'm wondering how we can do this?

for example:

if (list.Any(x => x.Name == Leia))
{
   //list of Foo's doesn't have any foo with the name 'Leia'
   var foo = db.GetFoo("Leia");
   foos.Add(foo);
}

Initially, i was thinking of using Double-checked locking but i'm a bit unsure if that's the correct path I should be taking .. especially after reading a bit about it and the suggestion of using Lazy<T> instead .. except my instance isn't the issue here .. it's the ITEMS in the instance that i'm worried about.

NOTE: The key here is not so much about a thread-safe collection (ie. like a ConcurrentBag / ConcurrentDictionary, etc) .. but more about reducing the calls to the DB.

Scenario:

  • 10 people hit the website at the same time
  • all 10 people see that the item is missing from the collection.
  • only 1x db.GetFoo("Leia"); is called
  • 9 others then retrieve the item from the collection (no db calls).

DISCLAIMER: I'm not sure if the title is correct - happy to hear suggestions on ammending it.

ChadT
  • 7,323
  • 2
  • 39
  • 56
Pure.Krome
  • 82,011
  • 105
  • 379
  • 615
  • ConcurrentDictionary<> maybe? – MickyD Aug 11 '16 at 02:29
  • @MickyD Updated post to be more accurate of the problem. – Pure.Krome Aug 11 '16 at 02:50
  • The operation you describe is called "caching". There are numerous Q&A on Stack Overflow discussing various techniques. See the marked duplicate for the basic .NET features available to help you with this. In addition to the suggestions in the marked duplicate, you could even just use a basic dictionary object (see https://en.wikipedia.org/wiki/Memoization). – Peter Duniho Aug 11 '16 at 03:20
  • If after researching your question and making an attempt to implement the techniques you find, you still have difficulty, please feel free to post a new question with a good [mcve] showing clearly what you've tried, with a precise description of what _specific_ issue you are having trouble with. – Peter Duniho Aug 11 '16 at 03:20
  • @PeterDuniho can you please explain why you think `caching` is the answer here? IMO, this is _not_ a standard caching problem .. or at least, the duplicate answer provided is not helping answer my problem. Remember, I'm not trying to cache the COLLECTION per say, but block other people calling the database while we insert an item into the collection. – Pure.Krome Aug 11 '16 at 04:11
  • Secondly, i'm not asking about multi-add's/inserts at the same time (`ConcurrentBag`, etc) .. so that's not a helpful answer, either. – Pure.Krome Aug 11 '16 at 04:12
  • _"if a Foo doesn't exist, grab it from the db"_ -- that's exactly what a cache does. Likewise, all of your specific requirements are simply standard implementation details of caches. The marked duplicate is your _starting point_. Anything beyond a reference to that post would be far too broad for Stack Overflow in any case. You are essentially asking someone else to hold your hand while you implement a cache from scratch. Yes, a desirable feature in many caches is to avoid having to query a DB more than once for any given object. That doesn't mean your question isn't really about caching. – Peter Duniho Aug 11 '16 at 05:03
  • Now that this has been locked - I cannot answer it. That said, the answer was actually suggested by @MickyD at the start of the post : Use a `ConcurrentDictionary` because that has a method on it called 'GetOrAdd`. So if the item doesn't exist (thread safe `Get`) then `Add` it (which is a call to my _expensive_ method). Works perfectly! So again, I felt that the answer was not *caching*. I guess some people consider _all_ collections as a cache .. /shrug. Thanks @MickyD! – Pure.Krome Aug 11 '16 at 07:18
  • 1
    You're quite welcome good sir. :) – MickyD Aug 11 '16 at 10:16

0 Answers0