Question

I have a question about caching with Entity Framework code first. I need to cache my query's results and I came about something that I didn't know.

Func<T, bool> predicate does not work when filtering whilst Expression<Func<T, bool>> predicate does.

Maybe I'm missing the obvious.

Here is my scenario:

Whenever I call a method, e.g."GetOrders", I use a method called "GetCachedModels" internally to get the cached version.

When subsequently many calls are made with "GetOrders(customerNo)" it checks the cache and the get it from there if it's there. That is the theory.

However when using Func predicate it does not find the item, but when using the Expression version it does?

My question is how do you use "Expressions" with a Where clause on a list? The other solution would be to have a method for each search, e.g. "myservice.GetCustomer(etc..) or myservice.GetOrders(etc..) instead of generic myservice.GetAll(); Which means adding many methods to the interface.

mycode:

public interface IGenericRepository
    {
        IList<T> GetAll<T>() where T : class;
        IList<T> Find<T>(Func<T, bool> predicate) where T : class; //I use this so that I could use the predicate in an where clause against a list.
        etc....

    }

In my repository I have something like:

 public IList<T> Find<T>(Func<T, bool> predicate) where T : class
    {
        List<T> models = GetCachedModels<T>().ToList();  
        var result= models.Where(predicate).ToList();  --Does not work!!! tried also with(expression.Compile()).ToList(); !!still no results!!!!
        return result;
    }




internal IList<T> GetCachedModels<T>() where T : class
    {
        IList<T> models;                
        Type typeParameterType = typeof(T);
        string cacheName = string.Format("{0}Cache", typeParameterType.Name);
        object cacheView = DbCache.Get(cacheName);
        if (cacheView == null)
        {
            models = Set<T>().ToList();
            DbCache.Add(cacheName, models, DateTime.Now.AddHours(1));
        }
        else
        {
            models = (IList<T>)cacheView;
        }
        return models;
    }


    //below method works but cannot use cache!!!!

    public IList<T> Find<T>(Expression<Func<T, bool>> predicate) where T : class
    {
        return Set<T>().Where(predicate).ToList();
    }
Was it helpful?

Solution

Expression predicates works only for IQueryable interface. List doesn't inherit it, so if you want to use this expression, you need to return IQueryable in GetCachedModels method, and return Set, so it can query this data. And then you can place it.

Otherwise if you want to cache all items from Set, then you need to pass Func instead of Expression, and then use it in Where extension method, like this - http://dotnetfiddle.net/5YsIy3

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top