Today, web applications use distributed caches to boost application performance and scalability by caching frequently used data to reduce expensive database trips. These distributed caches span and synchronize multiple cache servers to let you scale linearly. A good distributed cache usually has a Cache Dependency feature to let you invalidate cached items when a cached item depends on changes.
A Cache Dependency can be key-based, file-based, or database-based. When data in any of these sources change, your cached item is automatically removed from the cache because the dependency was invalidated. This allows you to keep your cached data fresh and accurate.
Custom Cache Dependency in Distributed Cache
If you want your cached items to be dependent on data in various data sources as mentioned above, NCache provides the Custom Cache Dependency feature to implement your custom logic if none of the built-in invalidation strategies fulfill your requirements. For example, you might have an RSS feed (Rich Site Summary) that changes your data. If you have your own program to read this feed and want to invalidate certain cached items based on whatever changes you see in the RSS feed. In these situations, Custom Cache Dependencies are the perfect tool for enhanced application performance.
NCache provides three distinct custom dependency classes, i.e., ExtensibleDependency, BulkExtensibleDependency, and NotifyExtensibleDependency. A custom dependency provider implements your logic. Let’s demonstrate how easily you can implement these classes with NCache below.
Extensible Dependency Usage and Implementation
The ExtensibleDependency class allows you to implement your custom invalidation logic according to which the data is expired one item at a time. You only need to inherit your custom dependency class from ExtensibleDependency and then override its HasChanged property. When this property is returned as true, the dependent item will expire from the cache.
The following code shows how to add data into the cache using the Insert method with Extensible Dependency enabled.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// Specify the connection string string connectionString = ConfigurationManager.AppSettings["connectionstring"]; // Fetch the product to be added to the cache Product product = FetchProductFromDB(productId); // Specify the unique key of the item string key = $"Product:{product.ProductID}"; // Create a cacheItem var cacheItem = new CacheItem(product); // Create dictionary for dependency parameters IDictionary<string, string> param = new Dictionary<string, string>(); param.Add("ProductID", product.Id.ToString()); param.Add("ConnectionString", connectionString); // Create Extensible Dependency using Provider and Add it to Cache Item CustomDependency customDependency = new CustomDependency(ConfigurationManager.AppSettings["ProviderName"], param); cacheItem.Dependency = customDependency; // Add cacheItem to the cache with dependency cache.Insert(key, cacheItem); |
Bulk Extensible Dependency Usage and Implementation
NCache provides another class called BulkExtensibleDependency, where a bulk of custom dependencies are evaluated simultaneously. Unlike Extensible Dependency, where expiration on each item takes time, Bulk Extensible Dependency boosts the application’s performance as it removes the invalidated items from the cache in time. Users call .Expire() on the dependencies that need to be removed from the cache.
The following code shows how to add data into the cache using the Insert() with Bulk Dependency.
1 2 3 4 5 6 7 8 9 10 11 |
// Create dictionary for dependency parameters IDictionary<string, string> param = new Dictionary<string, string>(); param.Add("ProductID", products.Id.ToString()); param.Add("ConnectionString", _connectionString); // Create Bulk Extensible Dependency using Provider and Add it to Cache Item CustomDependency customDependency = new CustomDependency(ConfigurationManager.AppSettings["ProviderName"], param); cacheItem.Dependency = customDependency; // Add cacheItem to the cache with bulk dependency cache.Insert(key, cacheItem); |
Notification Based Extensible Dependency Usage and Dependency
In Notification Extensible Dependency or Notify Extensible Dependency, clients have all the control over how and when to call a dependency on an item. NCache provides an abstract class, NotifyExtensibleDependency, an extension of custom dependencies to implement this behavior.
The following code shows adding data using Insert() with Notification-based Custom Dependency.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
// Specify the connection credentials string endPoint = ConfigurationManager.AppSettings["EndPoint"]; string authKey = ConfigurationManager.AppSettings["AuthKey"]; string monitoredCollection = ConfigurationManager.AppSettings["MonitoredCollection"]; string leaseCollection = ConfigurationManager.AppSettings["LeaseCollection"]; string databaseName = ConfigurationManager.AppSettings["DatabaseName"]; string providerName = ConfigurationManager.AppSettings["ProviderName"]; // Fetch a sample customer from the database Customer customer = LoadCustomerFromDatabase(customerId); // Specify the unique key of the item string key = "Customer#" + customer.Id ; // Create dictionary for dependency parameters IDictionary<string, string> param = new Dictionary<string, string>(); param.Add("CustomerID", customer.Id); param.Add("EndPOint", endPoint); param.Add("AuthKey", authKey); param.Add("MonitoredCollection", monitoredCollection); param.Add("LeaseCollection", leaseCollection); param.Add("DatabaseName", databaseName); // Creating notification dependency CustomDependency cosmosDbDependency = new CustomDependency(providerName, param); // Create a cacheItem var cacheItem = new CacheItem(customer); cacheItem.Dependency = cosmosDbDependency; // Add cacheItem to the cache with notification dependency cache.Insert(key, cacheItem); |
Conclusion
When data in your custom data source changes, NCache invalidates the dependent cached items from the cache. NCache is responsible for running your custom dependency code, so you don’t need to worry about implementing your own separate program and hosting it in some reliable process. Try to explore it for your application-specific scenarios.