Key Dependency
There are situations when you want to keep a relationship among related cache data e.g. an order depends on a product. If the product is no longer available, all the dependent orders need to be removed too. Here you can use key dependency to maintain this relationship. Key dependency creates a dependency relationship between cached items.
Note
The dependent item is removed in case of two types of modifications in the master key:
- Update
- Remove
In NCache, dependent cache items and the ones on which others depend are aware of this relationship. So when an item on which other items depend is removed, all dependent items will be removed. However vice versa is not possible, i.e. on removal of the orders, which has dependency on any other item e.g. products, products will not be removed.
Key(s) can have two types of dependencies:
Multilevel Dependency
A cache item can have a dependency on any number of other items in the cache; resulting in the formation of a chain. The relation in this case will be 1:1 relationship.
For example, there are three data sets in a cache i.e. Products, Orders and OrderDetails. For an order placed on a particular product, the key of the OrderDetails depends on the key of the Orders. Similarly the key of the Orders depends on the key of the Products.
Which means that if the Product is deleted the Order and the OrderDetails are also deleted. The following diagram depicts the scenario visually.
Multiple Dependency
A single item can depend on more than one items in the cache. Similarly that item may depend on further multiple items. This may result in a 1:n relationship between the items.
For example in a cache, if an Order is placed by a Customer which contains a product, the Order depends on the Customer as well as the Product. Similarly, the OrderDetails depend on the Orders. The following diagram depicts the whole scenario visually.
Here if Customer is deleted, Orders as well as OrderDetails get deleted. Similarly if the Product is deleted, Orders as well as OrderDetails get deleted.
Note
Only the existing keys in cache can be specified for key dependency. Nonexistent key specified for key dependency will result in
OperationFailedException
whereas an object can be specified as being dependent on another key at the time of
addition.
Pre-Requisites for Using Key Dependency
- Include the following namespace in your application:
Alachisoft.NCache.Web.Caching
Alachisoft.NCache.Runtime
Alachisoft.NCache.Runtime.Dependencies
- The application must be connected to cache before performing the operation.
- Cache must be running.
- Make sure that the data being added is serializable.
- To ensure the operation is fail safe, it is recommended to handle any potential exceptions within your application, as explained in Handling Failures.
Add Data to Cache with Key Dependency
Key dependency
can be added by using the Add as well as Insert method which takes an overload of key dependency. The Add
method adds a new item in the cache whereas the Insert
method adds a new item with dependency and if the item already exists in the cache it overwrites its properties.
Important
Note that this API also specifies cache item priority for eviction as well as expiration, so the value for that parameter has been passed as Default
, as it is not discussed here.
The following example adds a customer in the cache along with its orders with the dependency of the orders on the customer. Which means as soon as the customer is deleted from the cache, the orders associated with that customer are also deleted from the cache.
try
{
// Pre-Condition: Cache is already connected
// Customer with CustomerID "ALFKI" exists in cache
Customer customer = FetchCustomerByCustomerID("ALFKI");
// Specify the key of the item
string customerKey = "Customer: ALFKI";
// Get order against the customer from cache
Order order = FetchOrderByCustomerId("ALFKI");
// Generate a unique key for order
string orderKey = $"Order:{order.OrderID}";
// Add order in cache with dependency on customer which already exists in cache
// The other properties i.e. expiration and eviction are set as default
cache.Insert(orderKey, order, new KeyDependency(customerKey), Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, Alachisoft.NCache.Runtime.CacheItemPriority.Default);
// Any change in the customer will result in the removal of order
// For successful addition verify using
// cache.Contains()
// Count
}
catch (OperationFailedException ex)
{
// NCache specific exception
if (ex.Message.Contains("One of the dependency keys does not exist."))
{
// If the master key doesnt exist in the cache
}
else
{
// Exception can occur due to:
// Connection Failures
// Operation performed during state transfer
// Operation Timeout
}
}
catch (Exception ex)
{
// Any generic exception like ArgumentNullException or ArgumentException
}
Recommendation: To ensure the operation is fail safe, it is recommended to handle any potential exceptions within your application, as explained in Handling Failures.
Add CacheItem to Cache with Key Dependency
CacheItem is a custom class provided by NCache which can be used to add data to the cache and also lets you set additional metadata associated with an object of this class. This metadata defines the properties of the item like dependencies, expirations and more. You can refer to all properties of CacheItem here.
The Add
method adds a new item in the cache whereas the Insert
method adds a new item with dependency and if the item already exists in the cache it overwrites its properties.
Important
Note that this API also specifies cache item priority for eviction as well as expiration, so the value for that parameter has been passed as Default
, as it is not discussed here.
The following example adds a CacheItem
order to the cache which is dependent on the customer in the cache which means as soon as the customer is updated or deleted, the order of the customer is already deleted from the cache.
try
{
// Pre-Condition: Cache is already connected
// Customer with CustomerID "ALFKI" exists in the cache
Customer customer = FetchCustomerByCustomerID("ALFKI");
// Specify the key of the item
string customerKey = "Customer: ALFKI";
// Get order against the customer from cache
Order order = FetchOrderByCustomerId("ALFKI");
// Generate a unique key for order
string orderKey = $"Order:{order.OrderID}";
// Create a new CacheItem for this order
CacheItem cacheItem = new CacheItem(order);
// Create a new dependncy on customer
cacheItem.Dependency = new KeyDependency(customerKey);
// Add/Update item with keydependency
cache.Insert(orderKey, cacheItem);
// For successful addition of cacheitem with dependency
// Update the key and check if cacheitem is present in cahce
// This can be done by using
// Cache.Contains()
// Count
}
catch (OperationFailedException ex)
{
// NCache specific exception
if (ex.Message.Contains("One of the dependency keys does not exist."))
{
// If the master key doesnt exist in the cache
}
else
{
// Exception can occur due to:
// Connection Failures
// Operation performed during state transfer
// Operation Timeout
}
}
catch (Exception ex)
{
// Any generic exception like ArgumentNullException or ArgumentException
}
Recommendation: To ensure the operation is fail safe, it is recommended to handle any potential exceptions within your application, as explained in Handling Failures.
Add Key Dependency on Multiple Keys
You can also add key dependency to an item which is dependent on multiple keys. This way a single item can be dependent on multiple items using the Add or Insert method.
The Add
method adds a new item in the cache whereas the Insert
method adds a new item with dependency and if the item already exists in the cache it overwrites its properties.
Important
Note that this API also specifies cache item priority for eviction as well as expiration, so the value for that parameter has been passed as Default
, as it is not discussed here.
The following example adds employee's data in the cache with the dependency of the employee on the territories. If any territory gets updated or deleted from the cache, the employee automatically gets deleted.
try
{
// Pre-condition: Cache is already connected
// Get product from database against given ProductID
Employee employee = FetchEmployeeByID(1);
// Generate a unique cache key for this product
string key = $"Employee:{employee.EmployeeID}";
// Territories with the keys exist in the cache
string territoryKey1 = "Territory: Westboro";
string territoryKey2 = "Territory: Bedford";
// Insert the keys of the territories in an array
string[] territories = new string[1];
territories[0] = territoryKey1;
territories[1] = territoryKey2;
//Adding cache item "Employee:1" with Dependency on a list of territory keys
cache.Insert(key, employee, new KeyDependency(territories), Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.Normal);
// For successful addition of item with dependency
// Update or remove the keys
// Verify if dependent key is present using:
// cache.Contains()
// cache.Count
}
catch (OperationFailedException ex)
{
// NCache specific exception
if (ex.Message.Contains("One of the dependency keys does not exist."))
{
// If the master key doesnt exist in the cache
}
else
{
// Exception can occur due to:
// Connection Failures
// Operation performed during state transfer
// Operation Timeout
}
}
catch (Exception ex)
{
// Any generic exception like ArgumentNullException or ArgumentException
}
Recommendation: To ensure the operation is fail safe, it is recommended to handle any potential exceptions within your application, as explained in Handling Failures.
Add Key Dependency to Existing Cache Item
NCache also provides you with the ease of adding key dependency to an item already present in cache, without re-inserting it into the cache.
Important
This approach is comparatively less lightweight and more cost efficient since items are already present in the cache.
Using SetAttribute() API
This is done through CacheItemAttribute class, which has the property of Dependency to be set against CacheItem
.
The attribute is then set against the existing key of the item, using the SetAttributes method of Cache
class.
The following example shows that an order as well as a customer is already present in the cache without dependency and dependency is added on the order using SetAttributes
such that if the customer is updated or removed in the cache, the order is automatically removed.
try
{
// Pre-condition: Cache is already connected
// Pre-condition: Both the items already exist in cache
string customerKey = "Customer: ALFKI";
string orderKey = "Order: 1001";
// Create a key dependency where order is depenent on customer
KeyDependency dependency = new KeyDependency(customerKey);
// Create a CacheItemAttribute for dependency
CacheItemAttributes attr = new CacheItemAttributes();
attr.Dependency = dependency;
// Set the attribute of dependency against the order
cache.SetAttributes(orderKey, attr);
// Monitor/Verify dependency through either:
// PerfMon Counters
// cache.Contains(key)
// cache.Count
}
catch (OperationFailedException ex)
{
// NCache specific exception
if (ex.Message.Contains("One of the dependency keys does not exist."))
{
// If the master key doesnt exist in the cache
}
else
{
// Exception can occur due to:
// Connection Failures
// Operation performed during state transfer
// Operation Timeout
}
}
catch (Exception ex)
{
// Any generic exception like ArgumentNullException or ArgumentException
}
Recommendation: To ensure the operation is fail safe, it is recommended to handle any potential exceptions within your application, as explained in Handling Failures.
Using AddDependency() Method
Key Dependency can also be added to existing items using the AddDependency method.
The following example shows that an order as well as a customer is already present in the cache without dependency and dependency is added on the order using AddDependency
such that if the customer is updated or removed in the cache, the order is automatically removed.
try
{
// Pre-condition: Cache is already connected
// Pre-condition: Both the items already exist in cache
string customerKey = "Customer: ALFKI";
string orderKey = "Order: 1001";
// Create a key dependency where order is depenent on customer
KeyDependency dependency = new KeyDependency(customerKey);
// Add dependency to the item using the AddDependency method
bool itemAdded = cache.AddDependency(orderKey, dependency, false);
// Verify successful addition wih dependency
if (itemAdded == true)
{
// Deppendency is added
}
else
{
// Dependency could not be added
}
}
catch (OperationFailedException ex)
{
// NCache specific exception
if (ex.Message.Contains("One of the dependency keys does not exist."))
{
// If the master key doesnt exist in the cache
}
else
{
// Exception can occur due to:
// Connection Failures
// Operation performed during state transfer
// Operation Timeout
}
}
catch (Exception ex)
{
// Any generic exception like ArgumentNullException or ArgumentException
}
Recommendation: To ensure the operation is fail safe, it is recommended to handle any potential exceptions within your application, as explained in Handling Failures.
See also
Multi Cache Key Dependency
Aggregate Dependency
Data Expiration
Sync Cache with External Source