Pavalisoft.Caching is an open source caching extension for .NET Standard written in C#, which provides single unified API for both MemoryCache and DistributedCache implementations.
The main goal of the Pavalisoft.Caching package is to make developer's life easier to handle even very complex caching scenarios and concentrate on functionality. It's additional feature CacheManager supports various cache providers and implements many advanced features which can be used in single project/application.
With Pavalisoft.Caching, it is possible to implement multiple layers of caching with multiple cache providers in one place, e.g. MemoryCache and DistributedCache, in just a few lines of code.
The below diagram explains the Pavalisoft.Caching API and its usage.
Complete Documentation is available at https://pavalisoft.github.io/Caching/ for Pavalisoft.Caching API
Refer https://github.com/pavalisoft/Caching/tree/master/Samples for reference implementations
- Pavalisoft.Caching.InMemory.Sample -
CacheManager
withInMemory
andDistributedCache
cache stores. - Pavalisoft.Caching.Redis.Sample -
CacheManager
withRedis
cache stores. - Pavalisoft.Caching.MySql.Sample -
CacheManager
withMySql
cache stores. - Pavalisoft.Caching.SqlServer.Sample -
CacheManager
withSqlServer
cache stores. - Pavalisoft.Caching.TagHelpers.Sample -
CacheManager
withCacheTagHelper
cache stores. - Pavalisoft.Caching.InMemory.NoConfigSample -
CacheManager
withInMemory
andDistributedCache
cache stores without using json configuration.
- Define the Cache Stores and Partitions in Caching configuration section in appSettings.json.
{
"Caching": {
"Stores": [
{
"Name": "InMemory",
"Type": "Pavalisoft.Caching.InMemory.InMemoryCacheStoreType, Pavalisoft.Caching.InMemory",
"StoreConfig": "{\"ExpirationScanFrequency\":\"00:05:00\"}"
},
{
"Name": "DistributedInMemory",
"Type": "Pavalisoft.Caching.InMemory.MemoryDistributedCacheStoreType,Pavalisoft.Caching.InMemory",
"SerializerType": "Pavalisoft.Caching.Serializers.JsonSerializer,Pavalisoft.Caching",
"StoreConfig": "{\"ExpirationScanFrequency\":\"00:05:00\"}"
},
{
"Name": "SqlServer",
"Type": "Pavalisoft.Caching.SqlServer.SqlServerDistributedCacheStoreType,Pavalisoft.Caching.SqlServer",
"SerializerType": "Pavalisoft.Caching.Serializers.JsonSerializer,Pavalisoft.Caching",
"StoreConfig": "{\"ExpiredItemsDeletionInterval\":\"00:05:00\", \"ConnectionString\":\"Data Source=localhost;Initial Catalog=DistributedCache;Integrated Security=True\", \"SchemaName\":\"store\", \"TableName\":\"Cache\", \"DefaultSlidingExpiration\":\"00:05:00\"}"
},
{
"Name": "MySql",
"Type": "Pavalisoft.Caching.MySql.MySqlDistributedCacheStoreType,Pavalisoft.Caching.MySql",
"SerializerType": "Pavalisoft.Caching.Serializers.JsonSerializer,Pavalisoft.Caching",
"StoreConfig": "{\"ExpiredItemsDeletionInterval\":\"00:05:00\", \"ConnectionString\":\"Data Source=localhost;User Id=root;Password=root;Allow User Variables=true\", \"SchemaName\":\"store\", \"TableName\":\"Cache\", \"DefaultSlidingExpiration\":\"00:05:00\"}"
},
{
"Name": "Redis",
"Type": "Pavalisoft.Caching.Redis.RedisDistributedCacheStoreType,Pavalisoft.Caching.Redis",
"SerializerType": "Pavalisoft.Caching.Serializers.JsonSerializer,Pavalisoft.Caching",
"StoreConfig": "{\"Configuration\":\"00:05:00\", \"InstanceName\":\"localhost\"}"
}
],
"Partitions": [
{
"Name": "FrequentData",
"StoreName": "InMemory",
"SlidingExpiration": "00:05:00"
},
{
"Name": "DistributedFrequentData",
"StoreName": "DistributedInMemory",
"SlidingExpiration": "00:05:00"
},
{
"Name": "MySqlLocalizationData",
"StoreName": "MySql",
"Priority": "NeverRemove"
},
{
"Name": "LocalizationData",
"StoreName": "SqlServer",
"Priority": "NeverRemove"
},
{
"Name": "MasterData",
"StoreName": "Redis",
"SlidingExpiration": "00:05:00"
}
]
}
}
- Add Pavalisoft.Caching to services. Also add the Pavalisoft.Caching.InMemory , Pavalisoft.Caching.MySql , Pavalisoft.Caching.Redis and Pavalisoft.Caching.SqlServer Cache store implementations to services based on usage.
...
//Import the below namespace to use InMemory and DistributedInMemory cache store implementations
using Pavalisoft.Caching.InMemory;
//Import the below namespace to use MySql cache store implementation
using Pavalisoft.Caching.MySql;
//Import the below namespace to use Redis Cache Store implementation
using Pavalisoft.Caching.Redis;
//Import the below namespace to use SqlServer Cache Store implementation
using Pavalisoft.Caching.SqlServer;
...
namespace Pavalisoft.Caching.Sample
{
public class Startup
{
...
public Startup(IConfiguration configuration)
{
...
Configuration = configuration;
...
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
...
// Adds CacheManager service to services
services.AddCaching()
// Adds InMemory and Distributed InMemory Cache Store implementations to CacheManager
.AddInMemoryCache()
// Adds MySql Cache Store implementations to CacheManager
.AddMySqlCache()
// Adds Redis Cache Store implementations to CacheManager
.AddRedisCache()
// Adds SqlServer Cache Store implementations to CacheManager
.AddSqlServerCache();
...
}
...
}
}
- Use
AddCaching(CacheSettings cacheSettings)
extension method to pass theCacheSettings
instead of json in appsettings.json file
...
//Import the below namespace to use InMemory and DistributedInMemory cache store implementations
using Pavalisoft.Caching.InMemory;
//Import the below namespace to use MySql cache store implementation
using Pavalisoft.Caching.MySql;
//Import the below namespace to use Redis Cache Store implementation
using Pavalisoft.Caching.Redis;
//Import the below namespace to use SqlServer Cache Store implementation
using Pavalisoft.Caching.SqlServer;
...
namespace Pavalisoft.Caching.Sample
{
public class Startup
{
...
public Startup(IConfiguration configuration)
{
...
Configuration = configuration;
...
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
...
// Adds CacheManager service to services
services.AddCaching(CreateCacheSettings())
// Adds InMemory and Distributed InMemory Cache Store implementations to CacheManager
.AddInMemoryCache()
// Adds MySql Cache Store implementations to CacheManager
.AddMySqlCache()
// Adds Redis Cache Store implementations to CacheManager
.AddRedisCache()
// Adds SqlServer Cache Store implementations to CacheManager
.AddSqlServerCache();
...
}
private static CacheSettings CreateCacheSettings()
{
return new CacheSettings
{
Stores = new List<CacheStoreDefinition>
{
new CacheStoreDefinition
{
Name = "InMemory",
Type = typeof(InMemoryCacheStoreType).AssemblyQualifiedName,
StoreConfig = JsonConvert.SerializeObject( new MemoryCacheOptions
{
ExpirationScanFrequency = new TimeSpan(0,5,0)
})
},
new CacheStoreDefinition
{
Name = "DistributedInMemory",
Type = typeof(MemoryDistributedCacheStoreType).AssemblyQualifiedName,
SerializerType = typeof(Serializers.JsonSerializer).AssemblyQualifiedName,
StoreConfig = JsonConvert.SerializeObject( new MemoryDistributedCacheOptions
{
ExpirationScanFrequency = new TimeSpan(0,5,0)
})
}
},
Partitions = new List<CachePartitionDefinition>
{
new CachePartitionDefinition
{
Name = "FrequentData",
StoreName = "InMemory",
SlidingExpiration = new TimeSpan(0,5,0)
},
new CachePartitionDefinition
{
Name = "DistributedFrequentData",
StoreName = "DistributedInMemory",
SlidingExpiration = new TimeSpan(0,5,0)
}
}
};
}
...
}
}
- Use CacheManager methods to add, get, refresh and remove items in Cache.
// Add required using statements
using Pavalisoft.Caching;
using Pavalisoft.Caching.Interfaces;
using Microsoft.Extensions.Primitives;
using System;
namespace Pavalisoft.Caching.Sample
{
public class CachingSample
{
private const string CachePartitionName = "FrequentData";
private readonly ICacheManager _cacheManager;
public CachingSample(ICacheManager cacheManager)
{
_cacheManager = cacheManager;
}
public AppUser GetAppUser(HttpContext httpContext)
{
var userName = httpContext.User.Identity.Name;
AppUser appUser;
// Try to get the appUser from cache
if (!_cacheManager.TryGetValue(CachePartitionName, userName, out appUser))
{
// If not available in Cache then create new instance of AppUser
appUser = new AppUser(userName);
// Add appUser object to Cache
_cacheManager.Set(CachePartitionName, userName, appUser); `
}
return appUser;
}
}
}
- Define the Cache Stores and Partitions in Caching configuration section in appSettings.json.
{
"Caching": {
"Stores": [
{
"Name": "InMemory",
"Type": "Pavalisoft.Caching.InMemory.InMemoryCacheStoreType, Pavalisoft.Caching.InMemory",
"StoreConfig": "{\"ExpirationScanFrequency\":\"00:05:00\"}"
},
{
"Name": "DistributedInMemory",
"Type": "Pavalisoft.Caching.InMemory.MemoryDistributedCacheStoreType,Pavalisoft.Caching.InMemory",
"SerializerType": "Pavalisoft.Caching.Serializers.JsonSerializer,Pavalisoft.Caching",
"StoreConfig": "{\"ExpirationScanFrequency\":\"00:05:00\"}"
},
{
"Name": "SqlServer",
"Type": "Pavalisoft.Caching.SqlServer.SqlServerDistributedCacheStoreType,Pavalisoft.Caching.SqlServer",
"SerializerType": "Pavalisoft.Caching.Serializers.JsonSerializer,Pavalisoft.Caching",
"StoreConfig": "{\"ExpiredItemsDeletionInterval\":\"00:05:00\", \"ConnectionString\":\"Data Source=localhost;Initial Catalog=DistributedCache;Integrated Security=True\", \"SchemaName\":\"store\", \"TableName\":\"Cache\", \"DefaultSlidingExpiration\":\"00:05:00\"}"
},
{
"Name": "MySql",
"Type": "Pavalisoft.Caching.MySql.MySqlDistributedCacheStoreType,Pavalisoft.Caching.MySql",
"SerializerType": "Pavalisoft.Caching.Serializers.JsonSerializer,Pavalisoft.Caching",
"StoreConfig": "{\"ExpiredItemsDeletionInterval\":\"00:05:00\", \"ConnectionString\":\"Data Source=localhost;User Id=root;Password=root;Allow User Variables=true\", \"SchemaName\":\"store\", \"TableName\":\"Cache\", \"DefaultSlidingExpiration\":\"00:05:00\"}"
},
{
"Name": "Redis",
"Type": "Pavalisoft.Caching.Redis.RedisDistributedCacheStoreType,Pavalisoft.Caching.Redis",
"SerializerType": "Pavalisoft.Caching.Serializers.JsonSerializer,Pavalisoft.Caching",
"StoreConfig": "{\"Configuration\":\"00:05:00\", \"InstanceName\":\"localhost\"}"
}
],
"Partitions": [
{
"Name": "FrequentData",
"StoreName": "InMemory",
"SlidingExpiration": "00:05:00"
},
{
"Name": "DistributedFrequentData",
"StoreName": "DistributedInMemory",
"SlidingExpiration": "00:05:00"
},
{
"Name": "MySqlLocalizationData",
"StoreName": "MySql",
"Priority": "NeverRemove"
},
{
"Name": "LocalizationData",
"StoreName": "SqlServer",
"Priority": "NeverRemove"
},
{
"Name": "MasterData",
"StoreName": "Redis",
"SlidingExpiration": "00:05:00"
}
]
}
}
- Add Pavalisoft.Caching to services. Also add the Pavalisoft.Caching.InMemory , Pavalisoft.Caching.MySql , Pavalisoft.Caching.Redis and Pavalisoft.Caching.SqlServer Cache store implementations to services based on usage.
...
//Import the below namespace to use InMemory and DistributedInMemory cache store implementations
using Pavalisoft.Caching.InMemory;
//Import the below namespace to use MySql cache store implementation
using Pavalisoft.Caching.MySql;
//Import the below namespace to use Redis Cache Store implementation
using Pavalisoft.Caching.Redis;
//Import the below namespace to use SqlServer Cache Store implementation
using Pavalisoft.Caching.SqlServer;
...
namespace Pavalisoft.Caching.Sample
{
public class Startup
{
...
public Startup(IConfiguration configuration)
{
...
Configuration = configuration;
...
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
...
// Adds CacheManager service to services
services.AddCaching()
// Adds InMemory and Distributed InMemory Cache Store implementations to CacheManager
.AddInMemoryCache()
// Adds MySql Cache Store implementations to CacheManager
.AddMySqlCache()
// Adds Redis Cache Store implementations to CacheManager
.AddRedisCache()
// Adds SqlServer Cache Store implementations to CacheManager
.AddSqlServerCache();
...
}
...
}
}
- Use
AddCaching(CacheSettings cacheSettings)
extension method to pass theCacheSettings
instead of json in appsettings.json file
...
//Import the below namespace to use InMemory and DistributedInMemory cache store implementations
using Pavalisoft.Caching.InMemory;
//Import the below namespace to use MySql cache store implementation
using Pavalisoft.Caching.MySql;
//Import the below namespace to use Redis Cache Store implementation
using Pavalisoft.Caching.Redis;
//Import the below namespace to use SqlServer Cache Store implementation
using Pavalisoft.Caching.SqlServer;
...
namespace Pavalisoft.Caching.Sample
{
public class Startup
{
...
public Startup(IConfiguration configuration)
{
...
Configuration = configuration;
...
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
...
// Adds CacheManager service to services
services.AddCaching(CreateCacheSettings())
// Adds InMemory and Distributed InMemory Cache Store implementations to CacheManager
.AddInMemoryCache()
// Adds MySql Cache Store implementations to CacheManager
.AddMySqlCache()
// Adds Redis Cache Store implementations to CacheManager
.AddRedisCache()
// Adds SqlServer Cache Store implementations to CacheManager
.AddSqlServerCache();
...
}
private static CacheSettings CreateCacheSettings()
{
return new CacheSettings
{
Stores = new List<CacheStoreDefinition>
{
new CacheStoreDefinition
{
Name = "InMemory",
Type = typeof(InMemoryCacheStoreType).AssemblyQualifiedName,
StoreConfig = JsonConvert.SerializeObject( new MemoryCacheOptions
{
ExpirationScanFrequency = new TimeSpan(0,5,0)
})
},
new CacheStoreDefinition
{
Name = "DistributedInMemory",
Type = typeof(MemoryDistributedCacheStoreType).AssemblyQualifiedName,
SerializerType = typeof(Serializers.JsonSerializer).AssemblyQualifiedName,
StoreConfig = JsonConvert.SerializeObject( new MemoryDistributedCacheOptions
{
ExpirationScanFrequency = new TimeSpan(0,5,0)
})
}
},
Partitions = new List<CachePartitionDefinition>
{
new CachePartitionDefinition
{
Name = "FrequentData",
StoreName = "InMemory",
SlidingExpiration = new TimeSpan(0,5,0)
},
new CachePartitionDefinition
{
Name = "DistributedFrequentData",
StoreName = "DistributedInMemory",
SlidingExpiration = new TimeSpan(0,5,0)
}
}
};
}
...
}
}
- To use
pavalisoft-cache
tag helper, add the below to _ViewImport.cshtml
@addTagHelper *, Pavalisoft.Caching.TagHelpers
- Use the
pavalisoft-cache
tag helper in the view wherever required.
<div class="col-md-12">
<h2>Pavalisoft Cache TagHelper</h2>
<div class="row">
<pavalisoft-cache cache-partition="FrequentData">
This will be cached in server memory. expires-after 05 minutes
</pavalisoft-cache>
</div>
<div class="row">
<pavalisoft-cache cache-partition="DistributedFrequentData">
This will be cached in server distributed memory. expires-sliding (05 minutes)
</pavalisoft-cache>
</div>
<div class="row">
<pavalisoft-cache cache-partition="MySqlLocalizationData">
This will be cached in MySQL distributed memory. expires-after 05 minutes
</pavalisoft-cache>
</div>
<div class="row">
<pavalisoft-cache cache-partition="LocalizationData">
This will be cached in Sql Server distributed memory. expires-after 05 minutes
</pavalisoft-cache>
</div>
<div class="row">
<pavalisoft-cache cache-partition="MasterData">
This will be cached in Redis distributed memory. expires-sliding (05 minutes)
</pavalisoft-cache>
</div>
</div>
The below classes are used for providing the StoreConfig
to the respective CacheStore
s.
- MemoryCacheOptions for
InMemoryStore
cache stores. - MemoryDistributedCacheOptions for
MemoryDistributedCacheStore
cache store. - RedisCacheOptions for
RedisDistributedCacheStore
cache store. - SqlServerCacheOptions for
SqlServerDistributedCacheStore
cache store. - MySqlCacheOptions for
MySqlDistributedCacheStore
cache store.
Below are the list of serializers options available, which can be used to serialize and deserialize object from and to Distributed Cache Stores.
- BinaryFormatter - Requires the classes decorated with
SerializableAttribute
to store into Distributed Cache Stores. - Newtonsoft.Json - Uses Newtonsoft.Json to serialize a class without
SerializableAttribute
.
Get latest builds from nuget
Getting started with Git and GitHub
- Setting up Git for Windows and connecting to GitHub
- Forking a GitHub repository
- The simple guide to GIT guide
- Open an issue if you encounter a bug or have a suggestion for improvements/features
Once you're familiar with Git and GitHub, clone the repository and start contributing.