Entity Framework Core is a modern version of the classic .NET Entity Framework data object relational mapping engine. EF Core is rearchitected and rewritten to make it lightweight and cross-platform. When using EF Core to access your application database, there may be delayed database response time during peak load times. This drastically compromises your EF Core application performance. As your application transaction load grows, you are able to accommodate request loads by linearly scaling the application tier with more application servers. However, you cannot add in more database servers to handle the increased load.
This is where a distributed cache such as NCache comes into play. You can cache the frequently accessed data to improve response times. The distributed nature of caching in NCache for Entity Framework Core ensures optimal performance under extreme transaction loads by making the cache linearly scalable too.
Using Caching in Entity Framework Core
NCache provides integration for caching in Entity Framework Core through Extension Methods. You can cache the result sets of LINQ queries whether they are for transactional data or reference data. The following extension methods are provided by NCache for EF Core.
Caching Your LINQ Query Results – FromCache()
Let’s take an example of an airline company website which wants to fetch flights to Hawaii in July. The result set is more frequently fetched thus caching it would be a good idea.
FromCache()
Extension Method first checks for the query result in cache, if it doesn’t exist in cache or has become stale, it is fetched from the database and added to cache too, resulting in faster response times for future requests.
Using NCache, you can store the query result set as either separate entities or as a single collection. Saving the result set in the cache as a whole collection is reasonable here as any change in the result set would require it to be completely updated from the database.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
using (var context = new FlightRecordsContext()) { var options = new CachingOptions { // To store as collection in cache StoreAs = StoreAs. Collection }; var resultSet = (from flight in context.Flights where flight.Destination == "Hawaii" && flight.Month == "July" select flight).FromCache(options).ToList(); } |
NCache Details Entity Framework Core Cache Configure EF Core with NCache
Preload Cache With All Reference Data – LoadIntoCache()
To use the cache as your primary and reliable data source for your reference data, your entire reference data should be in the cache first. Without this, you cannot expect correct results from your queries against the cache because some of the data might be in the database whereas the query is only searching the cache.
Loading reference data of your EF Core application in NCache makes the request access much faster. LoadIntoCache()
fetches the LINQ query result set from the database and loads the data into the cache.
This is how LoadIntoCache()
works under the hood:
Let’s go on with an example of a product catalog of an e-store. Storing each product as a separate entity makes it available for all kinds of query combinations and even faster fetches of a single product.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
using (var context = new NorthwindContext()) { var options = new CachingOptions { // To store the result as separate entities in cache StoreAs = StoreAs.SeperateEntities }; var resultSet = (from product in context.Products select product).LoadIntoCache(options); } |
NCache Details Entity Framework Core Cache NCache LINQ API Docs
Search Reference Data in Cache with LINQ – FromCacheOnly()
You must load the entire reference data in the cache if you want to run LINQ queries against it. Otherwise, your LINQ queries are invalid because some data resides in the database and the LINQ queries are not searching the database in this scenario. This is different by doing LINQ queries against your database and caching their result set.
The following architecture illustrates the query execution through EF Core on NCache now:
For example, fetching the product with a specific product ID is now much faster as the trip is only to the cache:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
using (var context = new NorthwindContext()) { var options = new CachingOptions { // To store the result as collection in cache StoreAs = StoreAs.Collection }; var resultSet = (from product in context.Products where product.ProductID == MatchingProductID select product).FromCacheOnly(); } |
Related Links: Entity Framework Core Cache NCache LINQ API Docs
Modifying EF Core Entities in the Cache – GetCache()
EF Core allows you to add and update entities in the database. So, to synchronize the cache with database and make the necessary changes to the entities already existent in the cache, NCache provides a cache handle which allows you to perform add, update and remove operations directly on the cache.
For example, if you want to add another customer in EF Core, after adding it in the database by calling SaveChanges()
on the database context, you can get the cache context by calling GetCache()
and call Insert()
on the cache instance returned.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
using (var database = new NorthwindContext()) { var cust = new Customers { CustomerId = "HANIH", ContactName = "Hanih Moos", ContactTitle = "Sales Representative", CompanyName = "Blauer See Delikatessen" }; var options = new CachingOptions { QueryIdentifier = new Tag("CustomerEntity"), Priority = Runtime.CacheItemPriority.Default }; Cache cache = database.GetCache(); //get NCache instance cache.Insert(cust, out string cacheKey, options); } |
Related Links: Entity Framework Core Cache NCache Cache Class Docs Scale EF Core Apps-Webinar
Concluding Thoughts
Incorporating caching in EF Core through NCache is simple and flexible. NCache provides a distributed caching framework which works well on multi-server environments, by giving you 100% uptime and data reliability by replication, without compromising the performance of the cache. Hence caching in Entity Framework Core with NCache fills the gaps of performance and scalability and makes it highly efficient.
Good article, Usually I used the Azure Cache for Redis to achieves the superior throughput and latency performance by storing data in memory instead of on disk. In terms of pricing very cheap and in terms of performance it adds a great value to response time.
Anyway, a great effort to explain the complex topic in plain word.