How to enable caching for specific tables?

Feb 26, 2015 at 2:38 PM
Hello,
is there a way to indicate enable cache for specific tables and dont for others?

I am looking for option to
  1. enable-all followed by disable few
  2. disable-all followed by enable few
  3. individual enable/disable
Is there option to do this?

Regards,
Amit Rangari
Feb 27, 2015 at 12:04 PM
Edited Feb 27, 2015 at 12:05 PM
You have to create your own caching policy. Using the airline example on the EFCache blog, I have created a prototype with this policy
public class MyPolicy : CachingPolicy
{
    protected override bool CanBeCached(ReadOnlyCollection<EntitySetBase> affectedEntitySets, string sql, IEnumerable<KeyValuePair<string, object>> parameters)
    {
        var names = affectedEntitySets.Select(e => e.Table);
        var hashIncoming = new HashSet<string>(names);

        var cacheable = new List<HashSet<string>>(new[]
        {
            new HashSet<string>(new[] {"TblAirline", "TblAircraft"}),
            new HashSet<string>(new[] {"TblAirline"}),
            new HashSet<string>(new[] {"TblAircraft"}),
        });

        return cacheable.Any(hs => hs.SetEquals(hashIncoming));
    }
}
Where TblAirline and TblAircraft are the table names.

In your DbConfiguration extension, register the policy
  Loaded +=
            (sender, args) => args.ReplaceService<DbProviderServices>(
                (s, _) => new CachingProviderServices(s, transactionHandler, new MyPolicy()));
Obviously you can make your policy as dynamic as you like to serve the 3 scenarios you have listed.
Marked as answer by moozzyk on 3/4/2015 at 10:31 AM
Coordinator
Mar 4, 2015 at 5:31 PM
What northern_munkey said.
Jul 22, 2015 at 4:59 PM
the e.Table in my code is returning null everytime with a Database first approach, any reason(s) for this?

the line var names = affectedEntitySets.Select(e => e.Table);
Jul 26, 2015 at 11:54 PM
Change the e.Table to e.Name and will work.
Jul 27, 2015 at 12:05 AM
moozzyk, if I do a query using a where, for sample, var people = (from t in db.Person where t.Name.Contains("John") select t).ToList(); and another query in the where with .Contains("Wagner"), the code are going to the database and not to the Cache. Is it an expected behavior? Is there a way where indicate jn the code some specific entities to be cached and verify them in the cache before go to the database?
Coordinator
Aug 3, 2015 at 1:58 AM
@solanoah - you should do e.Table ?? e.Name - EF will set the Table property only if the Name of the entity set is different than a Table name

@OliverAlexander - EF cache use the SQL query as part of the cache key. In your scenario your queries will produce different queries and therefore a trip to the database will be made. To achieve what you want EF cache would have to be able to understand that the second query is actually a subquery and returns only a subset of results returned by the first query. Supporting this would require that EF cache works on much higher level (query trees instead of SQL and Data Reader) and might require changes to EF code itself.

Thanks,
Pawel