Entity Framework (EF) Core Cache

Entity Framework (EF) Core is the rearchitected and rewritten version of the Entity Framework object relational mapping engine for .NET Core applications. It is very light-weight, extensible, and cross platform.

However, high transaction .NET Core applications using EF Core face performance and scalability bottlenecks in the database-tier under peak loads. This is because although you can linearly scale the application tier by adding more application servers, you cannot add more database servers to scale it.

But, if you use a distributed cache like NCache in your .NET Core applications, you can quickly remove these performance and scalability bottlenecks and handle extreme transaction loads.

EF Core Caching thru Extension Methods

Extension Methods is a feature of C# that allows you to extend existing classes and types without creating derived classes. An Extension Method is a special kind of static method but it is called as if it is an instance method on the extended class.

NCache has integrated its caching features in EF Core through Extension Methods. This makes using NCache from within an EF Core application very simple and straight forward. Below is a list of EF Core Extension Methods provided by NCache.

1. Caching Transactional Data: FromCache() / FromCacheAsync()

The most common data to cache in EF Core is transactional data. This is the frequently changing data that is created at runtime (e.g. customer, accounts, activities, etc.) and you cache it only for a short time during which your application reads it multiple times.

FromCache() Extension Method allows you to cache transactional data by caching the result set of your LINQ queries. See the example below.

// Load suppliers into the cache with the expiration options
IEnumerable suppliers = (from supplier in database.Suppliers
						where supplier.SupplierId < 10
						select supplier).FromCache(options);

      

Here, before going to the database to fetch this data, the FromCache() method checks the cache for this data. If found, it returns it from the cache. Otherwise, it fetches it from the database, caches it first so it’ll be there next time around, and then returns the results to the caller.

You have the option of either caching the entire collection as one item in the cache or break out all its entities and cache them separately. Breaking out is useful if you also want to individual fetch or update these entities. Below is the Async version of this method.

   // Load suppliers into the cache with the expiration options asynchronously
Task suppliersTask = (from supplier in database.Suppliers
							 where supplier.SupplierId < 10
							 select supplier).FromCacheAsync(options);

suppliersTask.Wait();
IEnumerable suppliers = suppliersTask.Result.ToList();

   

2. Caching Reference Data: LoadIntoCache() / LoadIntoCacheAsync()

Reference data is something you should cache entirely. This allows you to run LINQ queries only on the cache and never go to the database for it. Please note that if you don’t have the entire data-set in the cache, your LINQ query results are incorrect because they only check the cache and assume that the entire data-set is in the cache.

With LoadIntoCache() Extension Method, you can populate your EF Core cache with all your reference data. See the example below for populating your cache.

// Load ALL products into the cache as reference data
IEnumerable products = (from product in database.Products
					  select product)
					  .LoadIntoCache(out string cacheKey, options);

3. Searching Reference Data: FromCacheOnly() / FromCacheOnlyAsync()

Once you’ve loaded the cache with all the reference data, you can run LINQ queries on it instead of the database. This reduces pressure on your database and improves your application performance and scalability. See the example below.

// Query for discontinued products from the reference data cache
IEnumerable products = (from product in database.Products
					where product.Discontinued == true
					select product).FromCacheOnly();

Please note that your EF Core reference data cache must contain the entire dataset (e.g. Products in this case). Otherwise, your FromCacheOnly() Extension Method will only return whatever is in the cache as it does not check the database. And, this may be incorrect.

4. Updating the Cache: Cache Class for EF Core

Whenever you make changes to your Entities in EF Core, you can update the EF Core Cache with them by obtaining the “Cache” handle and the making the appropriate update method call. Below is an example.

// Initialize the database context
NorthwindContext database = new NorthwindContext();
	...
// Add some new entities to the database
database.Shippers.Add(shipperPandaExpress);
database.Shippers.Add(shipperTitanic);
database.SaveChanges();

Cache cache = database.GetCache();
cache.Insert(shipperPandaExpress, out cacheKey, options);
cache.Insert(shipperTitanic, out cacheKey, options);

By obtain a Cache class handle, you can directly add, update, or remove entities from EF Core. And, then updated data shows up in your LINQ queries. This gives you a lot more control over updating entities when your modifying data yourself. Below is the interface of Cache class.

namespace Alachisoft.NCache.EntityFrameworkCore
{
    public class Cache
    {
        public void Insert(object entity, out string cacheKey, CachingOptions options);
        public void Remove(object entity);
        public void Remove(string cacheKey);
        public void RemoveByQueryIdentifier(Tag tag);
    }
}

Why Use NCache as EF Core Cache?

Entity Framework Core does not come with its caching framework (like NHibernate does). However, NCache has developed a very flexible, powerful, and yet very simple caching framework for you. You should use it for the following reasons:

  • Use in multi-server environment: NCache is a distributed cache that works very well in a multi-server environment. If your .NET Core application is high transaction, the chances are that it is running in a multi-server environment where only NCache will work for you.
  • Extremely fast: NCache is an extremely fast in-memory distributed cache and gives you sub-millisecond response times.
  • Linear scalability: NCache never becomes a scalability bottleneck. It lets you add servers to the cache cluster to achieve linear scalability and handle extreme transaction loads.
  • Cache size grows infinitely: NCache provides cache partitioning and pools memory of all cache servers together for it. So, you can grow cache storage by simply adding more servers to the cache cluster.
  • Intelligent data replication: NCache intelligently replicates the cache and without compromising performance. So, you won't lose any cache data even if a cache server goes down.
  • NCache gives you 100% uptime: NCache has a self healing dynamic cache cluster with no single point of failure. As a result, NCache allows you to add or remove cache servers at runtime without stopping your application or the cache

Please see details of all NCache features on Edition Comparison page. Read more about NCache and download a full working 60-day trial of NCache from the links below.