Using NCache in EF Core and SQL Server

Today I'm going to show you how you can integrate NCache into your existing Entity Framework Core applications to gain the benefits of high performance and scalability. There is a lot to cover so, I'm just going to jump straight into it.

Sample EF Core Application

The first thing we have is this sample Entity Framework Core application that I have that is using Northwind SQL databases. So, if we come here you can see that I'm fetching these orders between these order IDs 10249 and 10268, and we can see that I'm fetching these customers from the USA, and these products between these product IDs 10 and 20. That's all that this sample is doing. Let's go ahead and take a look at the results that this is going to fetch for us from the database. Perfect. So, we can see that we fetch these products between 10 and 20, these 11 products, these 13 customers from the USA, and these 20 orders between those order IDs.

Sample App Results

So, now that the sample has run, let's take a look at the database that we are working with. So, as you can see we're working with Northwind databases, and these are the customers that we have existing already in our customers's table. So, that's all well and good, we've seen the sample work.

Sample App Results

Integration Steps

Now, let's talk about how we can integrate NCache into this existing Entity Framework Core application. We are going to do this using five very simple steps.

  1. Install NCache EF Core Nuget Package
  2. Add NCache EntityFrameworkCore Namespace
  3. Specify Cache Configurations in DbContext
  4. Make Models Serializable
  5. Use NCache EF Core Extension Methods
 

Install NCache EF Core Nuget Package

So, the first step is going to be to install the NCache Entity Framework Core NuGet package into the application. So, if I manage the NuGet packages for this application, we can see that I already have it installed the EntityFrameworkCore.NCache NuGet package that corresponds to NCache 5.3 SP2. Perfect. So, I'm just going to close this.

 

Add NCache EntityFrameworkCore Namespace

Let's take a look at the next step. So, the next step is to add the NCache Entity Framework Core namespace into our application. So, if I come up here I just need to add "using Alachisoft.NCache.EntityFrameworkCore". I am going to need to do the same for my context. So, I save this here, move over to the context, and I'm going to paste it there too and save it, perfect.

 

Specify Cache Configurations in Database Context

Now, the next step is to specify the cache configurations within the database context. Now, if I scroll down I'm looking for my ‘OnConfiguring’ method. So, there it is, the OnConfiguring method. And, over here what I'm going to do is I'm going to add the cache I'm working with so that's the ‘efcorecache’ here, and I add the ‘NCacheConfiguration.Configure’ and I say this cache and the dependency type to be SQL server since I'm working with a SQL server, perfect.

 

Make Models Serializable

And, now that that's done the next step is to make our models serializable. So, I'm just going to head over into my models, and I'm going to go to my customer, and I'm just going to add [Serializable], perfect. I'm going to copy this I'm going to go over to the order and paste it there, save it, and in the product, and just going to paste it there, perfect. So, now that that's done I'm just going to look at this employee and to show you that I've already marked all the other models as serializable, so I don't need to do this for any more models.

 

Use NCache EF Core Extension Methods

So, now that our models are marked as serializable that brings us to the fifth step. And, the fifth step is the most interesting where we will be using the actual NCache Entity Framework Core Extension Methods within our application. Now, this is going to depend on the use case for the data that is existing within our application, and these could be one of two use cases. We could either have transactional data or we could have reference data in our application.

Handling Transactional Data

So, if we talk about transactional data, and when we're talking about handling transactional data transactional data is the data that is expected to be read as well as written to extremely frequently. A good example of this data would be keeping a track record of flights. So, there are a lot of flights that happen within a day, and all of them have something different about them, so if you were logging them in a database you would constantly write new flights in, and that can be considered a transactional use case. So, when we have this kind of transactional use case in our applications, for such type of data we say that it is ideal to use the ‘FromCache’ extension method.

FromCache Extension Method

Now what the FromCache extension method does is the first time that the FromCache extension method works, it works and it behaves quite like a normal Entity Framework Core application where your entities are fetched back from the database. However, at this time the FromCache method populates those entities into the cache, and the benefit of this is that the next time you have to call those queries, or you need those entities in your application you are not going all the way back to the database to get those entities and instead you are quickly fetching those entities back from the cache and you receive the benefit of high performance and you quickly get all your data ready to go within your application.

Now, let's go ahead and actually make this implementation and take a look at how it works. So, coming back to our application what I'm going to do here is I'm going to work with orders and I'm going to add some order caching options, there we go, and I say I have ‘new CachingOptions()’ here, and I'm just going to define the ‘StoreAsType’ to be a ‘Collection’. So, I want all the orders to be stored as a single collection in the cache. I also want these to expire so, I'm going to add an expiration so I'm going to ‘SetSlidingExpiration’ I'm going to add a ‘TimeSpan()’ of 10 minutes so that these orders expire after 10 minutes, perfect. And, now that that's done I'm just going to scroll down here and I'm going to add the ‘.FromCache’ extension method and add the ‘order_caching_options’, perfect. That's all I need to do here.

var order_caching_options = new CachingOptions()
{
	StoreAs = StoreAs.SeparateEntities
};
order_caching_options.SetSlidingExpiration(new TimeSpan(0, 10, 0));

//Orders 
var order_resultset = context.Orders
		     .Where(o => o.OrderId >= 10249 && o.OrderId <= 10268)
		     .FromCache(order_caching_options)
		     .ToList();

Console.WriteLine($"Orders between 10249 and 10268 fetched: {order_resultset.Count}
\n--------------------------------------------------------------------------\n\n"
+ String.Format("{0,-25}  {1,-40}  {2,-10}", $"Order ID", $"Date", $"Shipper Name") + "\n");

order_resultset.ForEach(order =>
{
    Console.WriteLine(String.Format("{0,-25}  {1,-40}  {2,-10}", $"{order.OrderId}", $"{order.OrderDate}", $"{order.ShipName}"));
});

Now, before I run it, let's take a look at our cache. Now, here I have the ‘EFCoreCache’ setup on my two nodes we can see here. If you go to the Monitor we can see that it is fully connected and healthy and running and in a good shape with nothing inside. And, if we go to the statistics this tells us the same story, it's a healthy cache with zero items inside ready to go, perfect. Now, let's go ahead and run our application, and let's take a look at the results that we get, perfect.

Now that the application is run I'm just going to close this console window here, and we can see these requests that we got on our cache in this addition that occurred, and if we scroll down we can see this count, which means that our collection has been populated into the cache.

NCache Monitoring Tool

Now, if I run the ‘export-cachekeys’, perfect, we can see this collection that has been entered into the cache. Now, say I wanted to add each order as a separate entity, so what I'm going to do is I'm going to add ‘SeparateEntities’ to my ‘StoreAs’ type instead of collection I'm going to run this application again. And now what this is going to do that is instead of that single collection it is going to add those orders as separate entities. Now that the applications run I can close it, and we can see all this activity that happened, and more importantly these additions. These 16 and 4 additions, and this count that has gone up.

NCache Monitoring Tool

So, if we go over to Statistics we can see 16 and 5. Now, I'm just going to export the cache keys again, and we can see that we have a 21 cache count, and all our orders have been populated as separate entities into the cache as well as a collection. So, that's perfect, and that's sort of wraps up how the FromCache extension method is used.

Cache Keys

Handling Reference Data

Now, let's talk about how you handle reference data and what reference data is. Reference data is the type of data that is read a lot more frequently than it is ever written to. So, this is data that more or less remains pretty static. For example, you have a catalog of products. Now your products are not expected to change extremely frequently so that could be reference data that is consistently being read from the database, and is rarely if ever being modified. And, in the case of reference data, the recommendation is that you bring your entire working set of reference data into the cache, and then you only ever read from the cache whenever you want to fetch that reference data. Let me show you how you're going to do that.

So, the first method we have, or the second extension method that we have is ‘LoadIntoCache()’ extension method. Now, the LoadIntoCache() extension method is extremely powerful for loading your complete working set of data into the cache. So, this is going to go and run the query against the database, it's going to get the query result, and populate the entire query result into the cache, and then return that result back to the application.

LoadIntoCache Extension Method

And, this is useful again for bringing the data into the cache, and you can run this on regular intervals whenever you expect that data to change. So, if you expect the data to change within a week, you can run it again after a week to keep refreshing the data in the cache and to make sure that you do not receive partial results when querying only from the cache for these entities. Speaking of querying only from the cache the way you would do that is by using the ‘FromCacheOnly()’ extension method. Now, the FromCacheOnly() extension method only ever looks for data within the cache, and it never ever goes to the back end database to get those results. This is an extremely fast extension method, and it ensures that you receive the full performance benefit of in-memory caching as you receive all the entities from a clustered cache, and you're never looking into your database.

Now, let's go ahead and Implement these extension methods into our application. But, there is one prerequisite that we have to complete before using them. So, to use these reference data extension methods we would have to define the query indexes within our application, and this can be done in one of two ways. Now, I can dynamically make those query indexes here by adding the ‘[QueryIndexable]’ tag which is also going to bring in the namespace ‘NCache.Runtime.Caching’ into the application, and now, I've dynamically done this. But, I'm going to do this in another way. So, I'm going to comment this here, and if I come over to my cluster caches I can show you that I have already defined these query indexes on my cache as we can see here.

Query Indexes

So, since I've already done this I do not need to add them dynamically within my application. So, now that is been established I'm going to scroll down here and I have this bit of code here, and all this is doing, just going to uncomment it, is it's fetching the products from the database. It's going to store them as separate entities using the ‘LoadIntoCache()’ extension method, and that's all that this is going to do. So, now I'm going to go ahead and run this, and let's take a look at the results that this fetches, perfect.

//Load ALL Products Into Cache
var products_caching_option = new CachingOptions
{
    StoreAs = StoreAs.SeparateEntities
};
var all_products = (from products in context.Products
                    select products)
                    .LoadIntoCache(products_caching_option)
                    .ToList();
Console.WriteLine($"\n\nAll Products Loaded into cache : {all_products.Count}\n\n");
all_products.ForEach(product =>
{
    Console.WriteLine(String.Format("{0,-25}  {1,-40}  {2,-10}", $"{product.ProductId}", $"{product.ProductName}", $"{product.UnitPrice}"));
});

So, we can see that we got these 77 products loaded into the cache, and we can see this count that has spiked all the way up, these additions that have happened, and these requests that have come in. If we go to the stats we can see 42 and 57.

NCache Statistics

Now, I'm just going to export the cache Keys again, perfect. So, we can see these 99 items within our cache and our entire working set of products has been brought into the cache. Now, that we have our entire working set within the cache, it is safe for me to go back to where I was querying the products, so I'm just going to comment this, and we're going to go up and we're going to add the ‘FromCacheOnly()’ extension method where I was fetching my products, perfect. And, now that that's done I can simply go and run the application again. And, let's take a look at the results that my application fetches against that ‘FromCacheOnly()’ extension method. There we go.

Products Added to the Cache

So, we can see that we got the same number of products, those 11 products, so we know that we have a complete result here and we can see that this fetch occurred from within our cache, and this activity which means that this FromCacheOnly() extension method worked and fetch the results for us from the cache.

EF Core Specific NCache APIs

So, that's all for the FromCacheOnly() and LoadIntoCache() extension methods. Now we can talk about the EF Core specific NCache APIs. So, NCache gives you the ability where you don't necessarily have to use an extension method to insert or remove data from the cache. You can also fetch the cache handle from the context using the EF Core library and then using that cache handle you can insert independent entities and remove independent entities from the cache. One thing I would add here is that this is not the same as the NCache APIs available within the NCache SDK, and this is the API that is dedicated or specific to Entity Framework Core.

So, if we take a look at these APIs, and take a look at how they work. So, this is how we would use them. So, we would fetch the cache from the context, and then we would insert data into the cache by simply running a cache.Insert against the customer and providing an out string cache key. This cache key would be generated by the Entity Framework Core APIs. And, then when you want to remove a data, or remove some item from the cache using the same cache handle then you could, for example, find that data within the cache using a context.find and then simply perform a cache.Remove.

EF Core Specific NCache APIs

Now, let's go ahead and do these in our application. So, if I come back to my application here, and I'm going to scroll down here, I have this bit of code here that adds the customer to the cache. I'm just going to uncomment this code, and if you scroll up we can see that I'm simply getting the cache from the context creating this customer, and I want to store it as a separate entity, I want to save the changes and perform this cache.Insert, and then write out that I have added this customer into the cache. So, let's go ahead and run it and take a look at what this does.

//Add Customer Using Cache Handle
Cache cache = context.GetCache();
var cust = new Customer
{
    CustomerId = "HANIH",
    ContactName = "Hanih Moos",
    ContactTitle = "Sales Representative",
    CompanyName = "Blauer See Delikatessen",
};

var options = new CachingOptions
{
    StoreAs = StoreAs.SeparateEntities
};

context.Customers.Add(cust);
context.SaveChanges(true);

cache.Insert(cust, out string cacheKey, options);
Console.WriteLine($"Customer ID: {cust.CustomerId} -> Added to Cache");

So, we can see that we've added this customer into the cache. So, if I close this application, we can see this addition that's been performed these requests, and we can see a small slump, so we've gone from 42 to 43. If we go over to the statistics we can see 43 and 57 which completes 100. So, if I export the cache keys we can see that independent customer, there we go. So, we can see that independent separate entity that we have added into the cache. That is perfect.

Independent Customer

Now, let's go ahead and remove this customer. So, I'm just going to comment this bit of code. Again, I'm going to scroll down here, and uncomment this piece of code, and all this piece of code is doing is it is looking for the customer within the cache of the same customer name, and if it finds that customer it is going to remove it from the context, save the changes, then remove it from the cache. And, then it is going to print out that it has done so. Otherwise, it's going to say that it could not find the customer.

//Remove Customer Using Cache Handle
Cache cache = context.GetCache();
Customer customerToRemove = context.Customers.Find("HANIH");
if (customerToRemove != null)
{
    context.Customers.Remove(customerToRemove);
    context.SaveChanges(true);
    cache.Remove(customerToRemove);
    Console.WriteLine($"Customer ID: {customerToRemove.CustomerId} -> Removed from Cache");
}
else
{
    Console.WriteLine("could not find the customer within the cache");
}
Console.ReadLine();

So, let's go ahead and run this application and take a look at the results, perfect. So, we can see that the customer has been removed from the cache, and we can see in the statistics we've gone from 43 to 42, and the monitor would show the same thing, perfect.

Customer Removed from the Cache

So, now if we go back to the stats I'm just going to open up the NCache PowerShell, and I'm going to export the cache keys, perfect. And, we can see that we do not have that customer in our cache anymore. And, that is how you can add, and remove customers, or any data using the NCache EF Core specific APIs.

Next Steps

Download NCache

And, that brings us to the end of this demonstration, thank you so much. If you want to download NCache you can receive a free 30-Day trial and a complete fully featured working product from our downloads page. Let me take you there now. So, if we come here you can see here that these are the offerings for .NET that you can download for Windows and for Linux that NCache provides.

Try Playground

Also, you can try NCache out in the NCache Playground. And, you can actually get a feel for the product to see how the features work. So, if you go here to the Try Playground you can see that you can start this sandbox session for 30 minutes that lets you run some samples and lets you see what .NET and Java samples would run and feel like.

Schedule a Personalized NCache Demo

And lastly, you can book a personalized NCache demo where we would provide you with a one-hour technical session where we would discuss NCache architecture and features, and map them according to the use case that we find within your environments. And, to do that is extremely simple. You would simply need to come to our website here and schedule this personalized live demo from this page here. And, once you're here you can send that request out, we'll receive it and we'll schedule something. And, that brings us to the end of this demo. Thank you so much for watching, have a wonderful day. Goodbye.

What to Do Next?

© Copyright Alachisoft 2002 - . All rights reserved. NCache is a registered trademark of Diyatech Corp.