I have the following simple cache class that I want to use to cache items frequently read from the database.
public class Cache<TKey, TElement>
where TElement : class
{
private Dictionary<TKey, TElement> cache = new Dictionary<TKey, TElement>();
private Func<TElement, TKey> dbKey;
public Cache(Func<TElement, TKey> dbKey)
{
this.dbKey = dbKey;
}
public TElement Get(TKey key, DataContext db)
{
if (cache.ContainsKey(key)) return cache[key];
// This line throws exception. See below
var value = db.GetTable<TElement>().SingleOrDefault(x => dbKey(x).Equals(key));
if (value != null) cache[key] = value;
return value;
}
}
The usage looks like this:
var db = new DataContext();
var userCache = new Cache<string, User>(u => u.Username);
userCache.Get("dave", db);
However, the indicated line throws a NotSupportedException with the message "Method 'System.Object DynamicInvoke(System.Object[])' has no supported translation to SQL." I understand why the exception is being thrown, but I'm not sure how to resolve it.
The cache is intended to operate in front of a number of different db tables, with different columns being used for the lookup key. My thought was to pass in a lambda to specify the lookup column, as you can see in the code. This works for IEnumerable, but not IQueryable.
Is there another way to achieve this in LINQ to SQL?