Spargine is a collection of open-source assemblies and NuGet packages designed for .NET 10, which I have been developing and maintaining since the release of .NET Framework 2. These assemblies are not only a core part of my projects but are also actively deployed in production environments across several companies I collaborate with.
Get Spargine
You can access the source code and NuGet packages here:
- GitHub: Spargine 10
- NuGet: dotNetDaveNuGet
For as long as I can remember, one of my top recommendations to developers during lectures or conference talks has been to cache data as much as possible to boost the performance of applications and services. Caching is a crucial technique for storing session data, frequently accessed configuration settings, results of expensive computations or database queries, temporary data that can be regenerated if lost, and much more. To aid developers in leveraging caching effectively, I created the InMemoryCache type in Spargine part of the DotNetTips.Spargine.Core assembly.
The Value of In-Memory Caching
In-memory caching offers several advantages and some disadvantages. Below is a comprehensive breakdown:
Advantages of In-Memory Caching
- Speed
In-memory caches are extremely fast since they operate directly within the application’s memory (RAM). This speed makes them ideal for low-latency, high-throughput applications. - Reduced Database Load
Storing frequently accessed data in memory reduces the load on underlying databases or external data sources, improving overall performance and scalability. - Scalability
Systems like Redis or Memcached support distributed use, allowing horizontal scaling to handle larger datasets or more requests. - Ease of Implementation
Many libraries and frameworks make implementing in-memory caching straightforward with minimal configuration. - Customizable Expiration Policies
Cached items can have time-to-live (TTL) settings, enabling automatic expiration of stale data and keeping the cache relevant. - Improved User Experience
Faster response times result in smoother user interactions, particularly for applications requiring real-time or near-real-time performance. - Flexibility
In-memory caches can store any serializable data structure, including objects, collections, and precomputed results.
Disadvantages of In-Memory Caching
- Volatility
Data stored in memory is lost if the application crashes or the server restarts, potentially causing downtime or re-computation. - Limited Capacity
Cache size is constrained by available memory (RAM), and large datasets may require more complex partitioning. - Consistency Challenges
Synchronizing cached data with the source of truth (e.g., a database) can be difficult, particularly in distributed systems. - Cold Cache Problem
Performance may degrade temporarily when the cache is initially empty or after being cleared. - Complexity in Management
Managing in-memory caches at scale requires eviction policies, handling cache misses, and monitoring usage. - Cost
RAM is more expensive than disk storage, increasing infrastructure costs for applications with large data needs. - Concurrency Issues
High-concurrency environments require thread-safe cache implementations to prevent data corruption or race conditions. - Security Risks
Storing sensitive data in memory poses security risks unless the cache is properly secured against unauthorized access.
Understanding these trade-offs will help you determine whether in-memory caching is suitable for your application and how to address its limitations effectively.
Introducing InMemoryCache
The InMemoryCache type in Spargine simplifies implementing in-memory caching, providing powerful and customizable functionality. Below is an overview of its key features and methods.
Using InMemoryCache to Add an Item
Adding an item to the cache is straightforward:
var cache = InMemoryCache.Instance;
var futureDate = DateTimeOffset.Now.AddMinutes(30);
cache.AddCacheItem(person.Id, person, futureDate);
Properties
- Cache()
Gets the MemoryCache instance used by InMemoryCache. - Instance()
Gets the singleton instance of InMemoryCache.e.
Methods
Below is a detailed list of methods available:
Adding Items
- AddCacheItem(IDataModel<T, TKey) item)
Adds an item to the cache with a timeout of 20 minutes. IDataModel is a Spargine interface. - AddCacheItem(IDataModel<T, TKey) item, DateTimeOffset timeout)
Adds an item to the cache with a custom expiration time.IDataModel is a Spargine interface. - AddCacheItem(IDataModel<T, TKey) item, TimeSpan timeout)
Adds an item to the cache with a custom expiration time. IDataModel is a Spargine interface. - AddCacheItem(IDataRecord item)
Adds an item to the cache with a timeout of 20 minutes. IDataRecord is a Spargine interface. - AddCacheItem(IDataRecord item, DateTimeOffset timeout)
Adds an item to the cache with a custom expiration time.IDataRecord is a Spargine interface. - AddCacheItem(IDataRecord item, TimeSpan timeout)
Adds an item to the cache with a custom expiration time. IDataRecord is a Spargine interface. - AddCacheItem<T>(string key, T item)
Adds an item to the cache with a timeout of 20 minutes. - AddCacheItem<T>(string key, T item, DateTimeOffset timeout)
Adds an item to the cache with a custom expiration time. - AddCacheItem<T>(string key, T item, TimeSpan timeout)
Adds an item to the cache with a custom timeout. - AddCacheItemAsync(IDataModel<T, TKey) item)
Asynchronously adds an item to the cache with a timeout of 20 minutes. IDataModel is a Spargine interface. - AddCacheItemAsync(IDataModel<T, TKey) item, DateTimeOffset timeout)
Asynchronously adds an item to the cache with a custom expiration time. IDataModel is a Spargine interface. - AddCacheItemAsync(IDataModel<T, TKey) item, TimeSpan timeout)
Asynchronously adds an item to the cache with a custom timeout. IDataModel is a Spargine interface. - AddCacheItemAsync(IDataRecord item)
Asynchronously adds an item to the cache with a timeout of 20 minutes. IDataRecord is a Spargine interface. - AddCacheItemAsync(IDataRecord item, DateTimeOffset timeout)
Asynchronously adds an item to the cache with a custom expiration time. IDataRecord is a Spargine interface. - AddCacheItemAsync(IDataRecord item, TimeSpan timeout)
Asynchronously adds an item to the cache with a custom timeout. IDataRecord is a Spargine interface. - AddCacheItemAsync<T>(string key, T item)
Asynchronously adds an item to the cache with a timeout of 20 minutes. - AddCacheItemAsync<T>(string key, T item, DateTimeOffset timeout)
Asynchronously adds an item to the cache with a custom expiration time. - AddCacheItemAsync<T>(string key, T item, TimeSpan timeout)
Asynchronously adds an item to the cache with a custom timeout. - AddCacheItemBatch<T>(IDictionary<string, T> items)
Adds multiple items to the cache at once with the default timeout. - AddCacheItemWithCallback<T>(string key, T item, TimeSpan timeout, PostEvictionDelegate postEvictionCallback)
Adds an item to the cache with a post-eviction callback. - AddCacheItemWithChangeToken<T>(string key, T item, TimeSpan timeout, IChangeToken changeToken)
Adds an item to the cache with a change token for dependency-based invalidation. - AddCacheItemWithCombinedExpiration<T>(string key, T item, TimeSpan slidingExpiration, TimeSpan absoluteExpiration)
Adds an item to the cache with both sliding and absolute expiration for optimal control. - AddCacheItemWithDependency<T>(string key, T item, TimeSpan timeout, CancellationTokenSource dependencyTokenSource)
Adds an item to the cache with a dependency on a CancellationTokenSource, allowing grouped invalidation. - AddCacheItemWithPriority<T>(string key, T item, TimeSpan timeout, CacheItemPriority priority): Adds an item to the cache with a specified priority level.
- AddCacheItemWithSize<T>(string key, T item, TimeSpan timeout, long size)
Adds an item to the cache with a specified size for size-aware caching. - AddCacheItemWithSlidingExpiration<T>(string key, T item, TimeSpan slidingExpiration)
Adds an item to the cache with sliding expiration.
Retrieving Items
- GetCacheItem<T>(string key): Gets the cache item associated with the specified key.
- GetCacheItemAsync<T>(string key): Asynchronously gets the cache item associated with the specified key.
Cache Management
- GetCacheItem<T>(string key)
Gets the cache item associated with the specified key. - GetCacheItemAsync<T>(string key)
Asynchronously gets the cache item associated with the specified key. - GetCacheItemBatch<T>(IEnumerable<string> keys)
Gets multiple cache items at once. - GetOrCreateAsync<T>([DisallowNull] string key, [DisallowNull] Func<CancellationToken, Task<T>> factory, TimeSpan? timeout = null, CancellationToken cancellationToken = default)
Gets the cache item associated with the specified key, or creates and caches it asynchronously if it does not exist. Ensures that only one factory delegate executes per key at a time (single-flight), preventing duplicate work. - GetOrCreateAsync<T>(string key, Func<CancellationToken, Task<T>> factory, DateTimeOffset absoluteExpiration, CancellationToken cancellationToken)
Gets the cache item associated with the specified key, or creates and caches it asynchronously if it does not exist. Ensures that only one factory delegate executes per key at a time (single-flight), preventing duplicate work. - PeekCacheItem<T>([DisallowNull] string key, out T? value)
Peeks at a cache item without updating statistics or access time. - TryGetValue<T>([DisallowNull] string key, out T? value)
Attempts to get the cache item associated with the specified key.
Cache Management
- Clear()
Clears all items from the cache. - Compact(double percentage)
Compacts the cache by the specified percentage. - ContainsKey(string key)
Determines whether the cache contains an item with the specified key. - Count()
Gets the count of items currently stored in the cache. - CreateCacheDependency(string dependencyKey)
Creates a CancellationTokenSource that can be used to link multiple cache entries together for grouped invalidation. - CreateCacheWithLimit(long? sizeLimit)
Creates the cache with a custom configuration including optional size limit. - GetAllKeys()
Gets all keys currently stored in the cache. - GetCacheStatistics()
Gets statistics about the current cache state. - InvalidateDependentCacheItems([DisallowNull] string dependencyKey)
Invalidates all cache entries that depend on the specified dependency key. - RefreshCacheItem([DisallowNull] string key, TimeSpan newTimeout)
Refreshes the expiration time of an existing cache item. - RemoveCacheItem(string key)
Removes the cache item associated with the specified key. - RemoveCacheItemBatch([DisallowNull] IEnumerable<string> keys)
Removes multiple items from the cache at once. - ResetStatistics()
Resets the cache statistics counters to zero.
Summary
The InMemoryCache type in Spargine is a robust and flexible solution for improving application performance and reliability. Its straightforward API enables developers to cache data effectively while addressing challenges like custom expiration policies and high-concurrency requirements. Detailed benchmarks are available on GitHub, showcasing their impact on performance.
Get Involved!
The success of open-source projects like Spargine relies on community contributions. If you find these updates useful or have ideas for further improvements, I encourage you to contribute by:
- Submitting pull requests
- Reporting issues
- Suggesting new features
Your input is invaluable in making Spargine an even more powerful tool for the .NET community.
If you are interested in contributing or have any questions, feel free to contact me via email at dotnetdave@live.com. Your support and collaboration are greatly appreciated!
Thank you, and happy coding!


Pick up any books by David McCarter by going to Amazon.com: http://bit.ly/RockYourCodeBooks
Make a one-time donation
Make a monthly donation
Make a yearly donation
Choose an amount
Or enter a custom amount
Your contribution is appreciated.
Your contribution is appreciated.
Your contribution is appreciated.
DonateDonate monthlyDonate yearlyIf you liked this article, please buy David a cup of Coffee by going here: https://www.buymeacoffee.com/dotnetdave
© The information in this article is copywritten and cannot be preproduced in any way without express permission from David McCarter.
Discover more from dotNetTips.com
Subscribe to get the latest posts sent to your email.

