ABP framework extends ASP.NET Core's distributed caching system.
ABP Framework extends the [ASP.NET Core distributed cache](https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed).
## Volo.Abp.Caching Package
> This package is already installed by default with the startup template. So, most of the time, you don't need to install it manually.
> This package is already installed by default with the [application startup template](Startup-Templates/Application.md). So, most of the time, you don't need to install it manually.
Volo.Abp.Caching is the core package of the caching system. Install it to your project using the package manager console (PMC):
[Volo.Abp.Caching](https://www.nuget.org/packages/Volo.Abp.Caching) is the main package of the caching system. You can install it a project using the add-package command of the [ABP CLI](CLI.md):
```
Install-Package Volo.Abp.Caching
abp add-package Volo.Abp.Caching
```
Then you can add **AbpCachingModule** dependency to your module:
```c#
using Volo.Abp.Modularity;
using Volo.Abp.Caching;
namespace MyCompany.MyProject
{
[DependsOn(typeof(AbpCachingModule))]
public class MyModule : AbpModule
{
//...
}
}
```
You need to run this command on a command line terminal in a folder containing a `csproj` file (see [other options](https://abp.io/package-detail/Volo.Abp.Caching) to install).
## `IDistributedCache` Interface
ASP.NET Core defines the `IDistributedCache` interface to get/set cache values. But it has some difficulties:
ASP.NET Core defines the `IDistributedCache` interface to get/set the cache values. But it has some difficulties:
* It works with **byte arrays** rather than .NET objects. So, you need to **serialize/deserialize** the objects you need to cache.
* It provides a **single key pool** for all cache items, so;
* You need to care about the keys to distinguish **different type of objects**.
* You need to care about the cache items of **different tenants** (see [multi-tenancy](Multi-Tenancy.md)).
* You need to care about the cache items of **different tenants** in a [multi-tenant](Multi-Tenancy.md) system.
> `IDistributedCache` is defined in the `Microsoft.Extensions.Caching.Abstractions` package. That means it is not only usable for ASP.NET Core applications, but also available to **any type of applications**.
> Default implementation of the `IDistributedCache` interface is the `MemoryDistributedCache` which works **in-memory**. See [ASP.NET Core's documentation](https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed) to see how to switch to **Redis** or another cache provider.
> Default implementation of the `IDistributedCache` interface is the `MemoryDistributedCache` which works **in-memory**. See [ASP.NET Core's documentation](https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed) to see how to switch to Redis or another cache provider.
See [ASP.NET Core's distributed caching document](https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed) for more information.
@ -50,52 +36,63 @@ ABP framework defines the generic `IDistributedCache<TCacheItem>` interface in t
`IDistributedCache<TCacheItem>` solves the difficulties explained above;
* It internally **serializes/deserializes** the cached objects. Uses **JSON** serialization by default, but can be overridden by replacing the `IDistributedCacheSerializer` service in the [dependency injection](Dependency-Injection.md) system.
* It automatically adds a **cache name** prefix to the cache keys based on the object type stored in the cache. Default cache name is the full name of the cache item class (`CacheItem` postfix is removed if your cache item class ends with it). You can use the `CacheName` attribute on the cache item class to set the cache name.
* It automatically adds the **current tenant id** to the cache key to distinguish cache items for different tenants (only works if your application is [multi-tenant](Multi-Tenancy.md)). Define `IgnoreMultiTenancy` attribute on the cache item class to disable this if you want to share the cached objects among all tenants in a multi-tenant application.
* Allows to define a **global cache key prefix** per application, so different applications can use their isolated key pools in a shared distributed cache source.
* It automatically adds a **cache name** prefix to the cache keys based on the object type stored in the cache. Default cache name is the full name of the cache item class (`CacheItem` postfix is removed if your cache item class ends with it). You can use the **`CacheName` attribute** on the cache item class to set the cache name.
* It automatically adds the **current tenant id** to the cache key to distinguish cache items for different tenants (if your application is [multi-tenant](Multi-Tenancy.md)). Define `IgnoreMultiTenancy` attribute on the cache item class to disable this if you want to share the cached objects among all tenants in a multi-tenant application.
* Allows to define a **global cache key prefix** per application, so different applications can use their isolated key pools in a shared distributed cache server.
* ABP's distributed cache also **can tolerate errors** wherever possible and bypasses the cache. This is useful when you have temporary problems on the cache server.
### Usage
An example class to store an item in the cache:
````csharp
public class BookCacheItem
namespace MyProject
{
public string Name { get; set; }
public class BookCacheItem
{
public string Name { get; set; }
public float Price { get; set; }
public float Price { get; set; }
}
}
````
You can inject and use the `IDistributedCache<BookCacheItem>` service to get/set `BookCacheItem` objects.
Example usage:
You can inject and use the `IDistributedCache<BookCacheItem>` service to get/set `BookCacheItem` objects:
`IDistributedCache<TCacheItem>` interface assumes that the type of your cache key is `string` (so, you need to manually convert your key to string if you need to use a different kind of cache key). `IDistributedCache<TCacheItem, TCacheKey>` can be used when your cache key type is not `string`.
`IDistributedCache<TCacheItem>` interface assumes that the type of your **cache key** is `string` (so, you need to manually convert your key to string if you need to use a different kind of cache key). While this is not a big deal,`IDistributedCache<TCacheItem, TCacheKey>` can be used when your cache key type is not `string`.
### Usage
An example class to store an item in the cache:
````csharp
public class BookCacheItem
using Volo.Abp.Caching;
namespace MyProject
{
public string Name { get; set; }
[CacheName("Books")]
public class BookCacheItem
{
public string Name { get; set; }
public float Price { get; set; }
public float Price { get; set; }
}
}
````
Example usage (assumes that your cache key type is `Guid`):
* This sample service uses the `GetOrAddAsync()` method to get a book item from the cache.
* Since cache explicitly implemented as using `Guid` as cache key, `Guid` value passed to `_cache_GetOrAddAsync()` method.
* This example uses the `CacheName` attribute for the `BookCacheItem` class.
`IDistributedCache<TCacheItem, TCacheKey>` internally uses `ToString()` method of the key object to convert it to a string. If you need to use a complex object as the cache key, you need to override `ToString` method of your class.
@ -192,7 +205,41 @@ public class BookService : ITransientDependency
}
````
### DistributedCacheOptions
## Error Handling
TODO
## Configuration
### AbpDistributedCacheOptions
`AbpDistributedCacheOptions` is the main [options class](Options.md) to configure the caching.
**Example: Set the cache key prefix for the application**
```csharp
Configure<AbpDistributedCacheOptions>(options =>
{
options.KeyPrefix = "MyApp1";
});
```
> Write that code inside the `ConfigureServices` method of your [module class](Module-Development-Basics.md).
#### Available Options
* `HideErrors` (`bool`, default: `true`): Enables/disables hiding the errors on writing/reading values from the cache server.
* `KeyPrefix` (`string`, default: `null`): If your cache server is shared by multiple applications, you can set a prefix for the cache keys for your application. In this case, different applications can not overwrite each other's cache items.
* `GlobalCacheEntryOptions` (`DistributedCacheEntryOptions`): Used to set default distributed cache options (like `AbsoluteExpiration` and `SlidingExpiration`) used when you don't specify the options while saving cache items. Default value uses the `SlidingExpiration` as 20 minutes.
## Advanced Topics
### IDistributedCacheSerializer
`IDistributedCacheSerializer` service is used to serialize and deserialize the cache items. Default implementation is the `Utf8JsonDistributedCacheSerializer` class that uses `IJsonSerializer` service to convert objects to [JSON](Json.md) and vice verse. Then it uses UTC8 encoding to convert the JSON string to a byte array which is accepted by the distributed cache.
You can [replace](Dependency-Injection.md) this service by your own implementation if you want to implement your own serialization logic.
### IDistributedCacheKeyNormalizer
`IDistributedCacheKeyNormalizer` is implemented by the `DistributedCacheKeyNormalizer` class by default. It adds cache name, application cache prefix and current tenant id to the cache key. If you need a more advanced key normalization, you can [replace](Dependency-Injection.md) this service by your own implementation.