Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cache a Linq Query - is this possible?

So, this may seem like an edge case, but I'm simply wondering if this is possible. What I have is a combination of a static set and deferred set wrapped in an IEnumerable - for example:

public IEnumerable<T> MakeMyQuery<T>()
{
    // returns a List<T>
    var someStaticData = LoadMyStaticDataFromDatabase();

    // Returns IEnumerable<T>, but from another resource
    var deferredQuery = CreateADeferredQueryUsingYieldReturn(); 

    return someStaticData.Concat(deferredQuery);
}

So what happens here is that when I call .Take(someNumber) on my enumerable, it will return elements from my static Data first before attempting to evaluate the deferred component - effectively, I have "hidden" some potentially time consuming producing tasks behind the enumerable such that if I never need to get those elements, they actually never get evaluated because of the deferred nature of LINQ.

However, I don't think it's possible to cache this query for later use (I don't believe the state of the Iterator will be kept in cache, right?) Or is there an easy way to do this without enumerating the results to save?

Ideally, my flow would be like so:

public List<T> SomeMethod<T>(int numberOfGuys)
{
     IEnumerable<T> query = null;

     if(// Is in Cache)
       query = Cache["MyQuery"];
     else
     {
         query = MakeMyQuery();
         Cache["MyQuery"] = query;
     }

     return query.Take(numberOfGuys).ToList();
}

So I can re-use the same query over and over to request data, but potentially never have to requery the DB. Is there a way to do this?

like image 979
Tejs Avatar asked Feb 15 '13 19:02

Tejs


People also ask

How do you cache a query?

You can create a Cached Query right from the Explorer. To cache a query, go ahead and save the query first. Fig 1: Press the button to "Save" the query. Then, to cache your most important queries select the “Enable Caching” checkbox and enter a refresh rate.

Why LINQ is faster than SQL?

The popular answer is that LINQ is INtegrated with C# (or VB), thereby eliminating the impedance mismatch between programming languages and databases, as well as providing a single querying interface for a multitude of data sources.

Does LINQ ever return null?

in conclusion no, it won't return null since null can't say sequence contains no elements it will always say object reference not set to an instance of an object ;) Does this answer the question?

How are LINQ queries executed?

LINQ queries are always executed when the query variable is iterated over, not when the query variable is created. This is called deferred execution. You can also force a query to execute immediately, which is useful for caching query results.


1 Answers

I think you want to cache the result of query.Take(numberOfGuys).ToList() in a new List. Before calling MakeMyQuery() you could look at the number of elements in your cached list (if it exists) and if the number of elements in your cached list is greater or equal to numberOfGuys then you'd return the numberOfGuys from your cached list. Otherwise you'd replace your cached list with the new result of query.Take(numberOfGuys).ToList().

As default.krammer pointed out, what you probably really want to cache is the result of LoadMyStaticDataFromDatabase() since if numberOfGuys is always less than LoadMyStaticDataFromDatabase(), you will end up hitting the DB repeatedly until numberOfGuys is greater than the number returned by LoadMyStaticDataFromDatabase(). So you could do a combination of caching LoadMyStaticDataFromDatabase() in the MakeMyQuery<T>() method and also caching query.Take(numberOfGuys).ToList() in SomeMethod<T>(int numberOfGuys), which would allow you to only hit the DB once, but still take advantage of the deferred execution of your IEnumerable<T>.

like image 106
Jacob VanScoy Avatar answered Oct 17 '22 03:10

Jacob VanScoy