Distributed cache is becoming very popular because it is a powerful way to boost your application performance and scalability and handle extreme transaction load without slowing down. Both .NET and Java applications are using it more and more each day.
But, one challenge people face with distributed cache is how to map and store relational data in a HashTable (key, value) pairing storage that a distributed cache is. Most caches today do not provide any mechanism to handle this. Because key-value stores use a flat data structure, they lack the native foreign-key constraints found in relational databases. Today, I will discuss Data Dependency which ASP.NET Cache provides, and that NCache incorporated from day one.
Key Takeaways
The Core Challenge: Distributed caches utilize a flat HashTable (key-value) data model, making it difficult to natively preserve relational database hierarchies and referential integrity constraints.
The Data Dependency Solution: NCache addresses this by incorporating Data Dependency (originally from ASP.NET Cache), allowing developers to link cached items across keys to mirror database constraints.
Automated Cache Invalidation: When a primary cached item (Item B) is updated or removed from the distributed cluster, any dependent item linked to it (Item A) is automatically purged to eliminate stale data.
Supported Architectural Layouts: NCache natively manages one-to-one, one-to-many, many-to-many, and multi-tier cascading relationships directly within the distributed cache using the KeyDependency class.
Just like ASP.NET Cache, in NCache, Data Dependency allows you to specify a dependency in the distributed cache between two cached items. Cached item A depends on cached item B. And, if B is ever updated or removed from the distributed cache, A is automatically removed. This ensures that if there is a referential integrity constraint between A and B in the database that it is also honored in the distributed cache. You can also specify cascading Data Dependency where A depends on B and B depends on C. Then, if you update or remove C, A and B are both removed. Here is a brief example of Data Dependency:
NCache Details Managing Relational Data Data Dependency Docs
Data Dependency lets you create one-to-one, one-to-many, and many-to-many relationships in the distributed cache. Here is how you would handle different scenarios:
How to Map a One-to-One Cache Dependency
A has one-to-one with B. Add B without any Data Dependency. Then, add A and specify a Data Dependency for B. If A and B both have a mutual dependency, then when update B afterwards and specify a dependency on A.
How to Map a One-to-Many Cache Dependency
A has one-to-many with B. Add A first without any Data Dependency. Then, add one or more B items and specify a Data Dependency for the given A for all of them. This way, if A is updated or removed, all of B’s will be removed automatically by NCache.
How to Map a Many-to-Many Cache Dependency
A and B have many-to-many with each other. Add one or more A’s. Then, add one or more B’s and specify Data Dependency for the appropriate A’s. Then, go back and update A’s to specify Data Dependency on appropriate B’s.
The table below maps how NCache automatically handles relational database structures and cross-key invalidation:
| Relationship Type | Primary Item Status | Dependent Item Action | Use Case Example |
|---|---|---|---|
| One-to-One | Item B is removed/updated | Item A is automatically removed | Customer Profile linked to an Account |
| One-to-Many | Parent Item A is removed/updated | All Child B items are removed | Order Record linked to multiple Order Items |
| Cascading Dependency | Base Item C is removed/updated | Dependent B and A items are removed | Multi-tier relational database hierarchies |
Here is a simple example of creating one-to-one dependency in cache.
|
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 |
public static void CreateDependencies(ICache _cache) { try { string keyB = "objectB-1000"; Object objB = new Object(); string keyA = "objectA-1000"; Object objA = new Object(); // Initializing cacheItems var itemOne = new CacheItem(objA); var itemTwo = new CacheItem(objB); // Adding objA dependent on ObjB itemOne.Dependency = new KeyDependency(keyB); //Adding items to cache _cache.Add(keyB, itemTwo); _cache.Add(keyA, itemOne); // Removing "objB" automatically removes “objA” as well _cache.Remove(keyB); _cache.Dispose(); } catch (Exception e) { throw; } } |
So, NCache allows you to take advantage of Data Dependency and specify data relationships in the distributed cache. Download a fully working 60-day trial of NCache Enterprise and try it out for yourself.
NCache Details Ncache Download Edition Comparison
Frequently Asked Questions (FAQ)
Q: In what order should items be added to the cache when setting up a Key Dependency?
A: The independent item (the target key) must always be added to the cache before the dependent item is inserted. For example, in a one-to-one relationship where Item A depends on Item B, you must add Item B to the cache first. When you subsequently add Item A, you assign its Dependency property to point to the key of Item B.
Q: What happens to child items in a one-to-many relationship if the parent item is updated instead of deleted?
A: If the parent item (Item A) is either updated or removed from the distributed cache, NCache automatically removes all the dependent child items (B items) linked to it. This ensures that any modification to a primary record instantly clears out potentially stale or mismatched relational data across the cluster.
Q: How do you configure a bidirectional (mutual) dependency between two cached items?
A: To make two items depend on each other mutually, you must perform a two-step insertion and update sequence:
- Add Item B to the cache normally without any initial data dependency.
- Add Item A to the cache and specify its KeyDependency targeting Item B.
- Go back and update Item B in the cache, assigning it a data dependency that targets Item A.
Q: Does NCache support multi-tier relational chains, and how do they behave during eviction?
A: Yes. NCache supports cascading Data Dependency, allowing you to build multi-tier relational chains (e.g., Item A depends on Item B, and Item B depends on Item C). If the base item at the top of the chain (Item C) is updated or removed, it triggers a cascading eviction that automatically purges both Item B and Item A from the cache.
Q: Which specific NCache API class is used to link key-value pairs for referential integrity?
A: Referential integrity between keys is established using the CacheItem object and the KeyDependency class. You instantiate a KeyDependency passing the target key string as a parameter, assign it to the Dependency property of your dependent CacheItem, and then add that item to the cache cluster.







Thanks for sharing the blog, it was well explained about data dependency, it was worth investing time reading this blog.
Hi Iqbal,Thank you for sharing imairnftove article. Can you please explain distributed cache? Does it mean by Cache maintained at different (physical) frontend servers and DB Server?I have a scenario Frontend Server (FS)1 is maintaing local cache C1. FS2 is maintaing its own local cache C2. FS3 is maintaning its own local cacheC3. There is DB Server that has global cache GC. All the local cache C1, C2, C3 need be to depends on GC. If GC is updated then all the local cache gets invalidated. I do not how this gonna work because In my opinon we cannot control the memory on the other system?Please throw some light on this.ThanksKhusi
NCache is an out of process in-memory distributed cache. It can form a cluster of cache nodes at runtime and can be distributed across multiple applications.
Here is how NCache will handle your scenario:
You can create a Global clustered cache (for example having 2 nodes in cluster) on the DB servers or dedicated cache servers and can then utilize “Client Cache” feature on each front end server FS1, FS2 and FS3. NCache Client cache is a local cache running on NCache client boxes (Web/App servers are NCache clients) and keeps a copy of data locally on the client box which is most frequently accessed from the clustered cache.
Subsequent calls for the same data will be served from local client cache directly giving more performance by saving network trips, client caches can also be in-proc in nature.
The data synchronization is managed automatically by NCache. In case of updates on the Global clustered cache, client caches will automatically invalidate/Remove items and will bring an updated copy from the clustered cache on subsequent access.
Hi Iqbal,
Thank you for sharing informative article. Can you please explain distributed cache? Does it mean by Cache maintained at different (physical) frontend servers and DB Server?
I have a scenario – Frontend Server (FS)1 is maintaing local cache C1. FS2 is maintaing its own local cache C2. FS3 is maintaning its own local cacheC3. There is DB Server that has global cache GC. All the local cache C1, C2, C3 need be to depends on GC. If GC is updated then all the local cache gets invalidated. I do not how this gonna work because In my opinon we cannot control the memory on the other system?
Please throw some light on this.
Thanks
Khusi
It’s really a nice and helpful piece of information. I’m glad that you shared this helpful info with us. Please keep us informed like this. Thanks for sharing.