In this post, we will discuss caching in entity framework core using NCache from scratch to complete integration.
What is NCache?
.NET, Java, and Node.js applications can benefit from NCache due to its fast and linear scalability. By caching application data, NCache reduces expensive database trips and is extremely fast and linearly scalable. For .NET, Java, and Node.js applications, NCache removes performance bottlenecks associated with data storage and databases.
What is EF Core?
Object-relational mapping is made easier with ADO.NET Entity Framework. An application is not required to write code to persist relational data in a database since it abstracts the underlying data from the database and presents the database schema as a conceptual schema.
With Entity Framework Core, you can create high transactional applications that cannot compromise scalability and performance while being lightweight, open source, and cross-platform. It is, however, unlikely that more servers can be added to the database tier in such critical cases, which causes it to become a bottleneck. Entity Framework Core has extensions that allow NCache to achieve this scalability and reliability.
A .NET server application like ASP.NET, Web Services, or Microservices is often utilized along with its ability to map a relation to an object. EF Core’s distributed caching can be used to eliminate scalability bottlenecks from database when there is a high network load, allowing applications to scale without database bottlenecks. How NCache can be integrated into EF Core is explained in this blog.
Why NCache and How does it work?
The application tier is linearly scaled with more application servers as our application transaction load increases. A larger number of database servers, however, is not sufficient to deal with the increased load. During this situation, distributed caches like NCache come in very handy. It is possible to speed up response times by caching frequently accessed data. Because NCache for Entity Framework Core is distributed, it provides optimal performance when dealing with high transaction loads.
NCache is very easy to integrate with EFCore. Three extension methods are presented in this post to explain how NCache works with EF Core.
- FromCache()
- GetCache()
- LoadIntoCache()
- FromCacheOnly()
A multiserver environment with NCach’s distributed caching does not compromise cache performance and ensures high data reliability. The performance and scalability gaps of Entity Framework Core are filled by NCache caching. Performance improves during high traffic periods when transaction load increases.
Install NCache Manager:
From the NCache Download Center (alachisoft.com), download NCache. In order to fully explore all the features, I highly recommend installing the Enterprises edition. If your machine does not already have .NET 6, install it before you begin the installation
The NChace Web Manager can then be run from localhost 8251 port, after you’ve completed the download and installation process.
A clustered or locally cache can be created using the NCache Manager application.
As part of this demonstration, a local cache called “myLocalCache” is created with Ncache Manager.
The NCahce Web Manager can be used to create a local cache. Click here to see how to do it.
NCache with EFCore:
As I did in my previous article on Clean Architecture, I’ll be using the same .NET Core application.
This project has different layers. With EF Core, we have a data access layer called HotelBook.Persistance.
The EntityFrameworkCore.NCache package can be installed with NuGet Package Manager.
Now that we’ve configured the NCache into EFCore, let’s go over how to use it.
Include the following code in the AddPersistence service collection method of PersistenceServiceRegistration.cs.
string cacheId = configuration.GetSection("NCacheConfig").GetSection("CacheId").Value.ToString();
NCacheConfiguration.Configure(cacheId, DependencyType.SqlServer);
Set your Cache ID in appSetting.jsom file as a Key value pair.
"NCacheConfig": {
"CacheId": "myLocalCache" //Replace "demoCache" with the name of your cache
}
myLocalCache is my localCache Name/Id
By passing CacheId and dependency type to the Configure method, the NcacheConfiguration class initializes the Ncache configuration. For us, it is SQLServer that is the dependency type
We’ll begin by looking at the FromCache() extension method.
FromCache()
We have an API that allows us to get a list of all hotAssume that when users log in to the application, the landing page will display all the details of all the hotels, so this will be one of our frequently-used APIs. API in our application. The database will be greatly relieved of load if the dataset is cached.
By using the FromCahce() extension method, a cache check is performed first on the query result. The database will be consulted if it is not available. Future response times will be faster as a result.
There are two ways to store query results: separately or as a single collection. When running this query, saving the results in the cache as a collection is more sensible, since the database will be updated immediately if any changes are made to the result set.
The Local cache statistics can be viewed after executing the query.
Client Connection
There has been one connection established, judging from the statistics.
public List<Hotel> ListAllHotels()
{
var options = new CachingOptions
{
// To store as collection in cache
StoreAs = StoreAs.Collection
};
var resultSet = (from cust in _dbContext.Hotels
select cust).FromCache(options);
return resultSet.ToList();
}
When the first call is made, the database will be fetched and cached data will be saved. It will not be necessary to hit the database when returning data from a Future call.
LoadIntoCache()
We use this extension method to load reliable reference data into our cache for our models, thereby making it our primary source of reliable reference data. By querying the database, the entire reference data will be loaded into cache. In some cases, your data may be in the database whereas your query only searches the cache, so you cannot always expect the correct results from the cache.
public List<Hotel> ListAllHotels()
{
var options = new CachingOptions
{
// To store as collection in cache
StoreAs = StoreAs.SeperateEntities
};
var resultSet = (from cust in _dbContext.Hotels
select cust).LoadIntoCache(options);
return resultSet.ToList();
}
In order to support the caching option, it has been decided to store it separately so that each hotel can be searched individually and is retrievable more quickly.
Data is loaded into a cache by LoadIntoCache from the database. If this method is executed, the database will always be retrieved, meaning that the database is always consulted.
FromCacheOnly():
The entire reference data must be loaded in the cache before using FromCacheOnly(). Whenever FromCacheOnly() is called, a cache search is conducted and results are returned, never a database search is performed. When using FromCacheOnly(), we should query only the reference data collected by LoadIntoCache(), which means that if you want a reliable result set, you should query only the reference data in the cache.
public List<Hotel> ListAllHotels()
{
var options = new CachingOptions
{
// To store as collection in cache
StoreAs = StoreAs.SeperateEntities
};
//FromCacheOnly
var resultSet = (from cust in _dbContext.Hotels
where cust.Name == "jack68815" ||cust.Name== "jack23939"
select cust).FromCacheOnly();
return resultSet.ToList();
}
By calling FromCacheOnly() instead of querying the database, the result set will be returned from the cache, instead of reaching the database. It doesn’t talk with database.
GetCache():
Database entities can be added and updated in the EF Core context. The cache context must also be updated whenever the context changes. Cache operations can be performed directly on NCache using its cache handle.
As part of the AddHotel() method, we will call SaveChanges(), GetCache(), and Insert() to add a new hotel to the EFCore.
var options = new CachingOptions
{
QueryIdentifier="HotelEntity",
Priority = Alachisoft.NCache.Runtime.CacheItemPriority.Default
};
var hotel = new Hotel { HotelId =new Guid(), Name="Gowtham"};
_dbContext.Hotels.Add(hotel);
_dbContext.SaveChanges();
Cache cache = _dbContext.GetCache(); //get NCache instance
cache.Insert(hotel, out string cacheKey, options);
The code above has inserted a new hotel record into the database. The record will be inserted into the cache context once the cache context has been obtained via GetCache().
Conclusion:
By demonstrating NCache’s function, how it works, and how an Entity Framework extension can be used to cache EF queries, we demonstrated how effective caching can be at reducing database load.