Caching with LINQPad.Extensions.Cache

One of the tools that I absolutely adore during my day-to-day development is LINQPad . If you are not familiar with this tool and you are a .NET developer, you should go to www.linqpad.net right now and install it. The basic version is free and feature-packed, though I recommend upgrading to the professional version. Not only is it inexpensive, but it also adds some great features like Intellisense1 and Nuget package support.

I generally use LINQPad as a simple coding environment for poking around my data sources, crafting quick coding experiments, and debugging. Because LINQPad does not have the overhead of a solution or project, like a development-oriented tool such as Visual Studio, it is easy to get stuck into a task. I no longer write throwaway console or WinForms apps; instead I just throw together a quick LinqPad query. I could continue on the virtues of this tool2, but I would like to touch on one of its utility features.

As part of LINQPad , you get some useful methods and types for extending LINQPad , dumping information to LINQPad's output window, and more. Two of these methods are LINQPad.Extensions.Cache and Utils.Cache. Using either Cache method, you can execute some code and cache the result locally, then use the cached value for all subsequent runs of that query. This is incredibly useful for caching the results of an expensive database query or computationally-intensive calculation. To cache an IEnumerable<T>  or IObservable<T>  you can do something like this:

var thingThatTakesALongTime = from x in myDB.Thingymabobs
                              where x.Whatsit == "thingy"
                              select x;
var myThing = LINQPad.Extensions.Cache(thingThatTakesALongTime);

Or, since it's an extension method,

var myThing = thingThatTakesALongTime.Cache();

For other types, Util.Cache  will cache the result of an expression.

var x = Util.Cache(()=> { /* Something expensive */ });

The first time I run my LINQPad code, my lazily evaluated query or the expression is executed by the Cache method and the result is cached. From then on, each subsequent run of the code uses the cached value. Both Cache methods also take an optional name for the cached item, in case you want to differentiate items that might otherwise be indistinguishable (such as caching a loop computation).

This is, as I alluded earlier, one of many utilities provided within LINQPad that make it a joy to use. What tools do you find invaluable? Do you already use LINQPad ? What makes it a must have tool for you? I would love to hear your responses in the comments.

Updated to correct casing of LINQPad, draw attention to Cache being an extension method for some uses, and adding note of Util.Cache3.

  1. including for imported data types from your data sources []
  2. such as its support for F#, C#, SQL, etc. or its built-in IL disassembly []
  3. because, apparently, I am not observant to this stuff the first time around. SMH []

7 thoughts on “Caching with LINQPad.Extensions.Cache”

    1. I cannot believe I never noticed that before. I have no defense. Completely missed that. The clues are all there.

    2. I have updated the entry to cover this and add info on `Util.Cache`. Thanks for the feedback and for LINQPad.

  1. For my use case, it would have been useful to be able to update the value saved in cache to store a list which i may or may not add results to over many runs. Do you know of a way to do that?

    1. I am not aware of a method to force a cache update (or clear the cached item); it would definitely be useful.

      However, you could use the version of `Cache` that takes a key name and gives a boolean `out` parameter. If that parameter is set to `true` (i.e. the returned value is a cached value), you could change the key and cache under a new value.

      With that in mind, you could perhaps abstract that away with a method like this (this is clearly a naive implementation but it gives the general idea).

      public IEnumerable Cache(IEnumerable toBeCached, string key, bool update)
      {
      	bool fromCache;
      	IEnumerable cachedValue;
      	int keyModifier = 0;
      	string realKey = key;
      	
      	do {
      		cachedValue = toBeCached.Cache(realKey, out fromCache);
      		realKey = String.Format("{0}{1}", key, keyModifier++);
      	} while (fromCache && update);
      	
      	return cachedValue;
      }
      

      Of course, this doesn't help with retrieving the latest value, so it would need to somehow know what the last used key modifier was.

  2. I have a list of data and wanted to cache results for each. I am making sure to set a unique cache key for each.

    What I noticed is if my list is short, Cache works nicely.

    When the list is long, it doesn't work. I am guessing there is a point where there is too much data cached and it starts deleting entries from cache 🙁

    Do you know of a way around this?

    1. I haven't used LINQPad in a while since my job shifted away from C#. The only way around it, as I can think of right now, would be to implement some sort of file-based caching so it persists across runs?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.