Skip to content

Commit a4b5ddf

Browse files
committed
docs: Add distributed entity caching
1 parent 0d891ac commit a4b5ddf

File tree

5 files changed

+206
-2
lines changed

5 files changed

+206
-2
lines changed

docs/en/Caching.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ ABP Framework extends the [ASP.NET Core distributed cache](https://docs.microsof
1010
1111
[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):
1212

13-
```
13+
```bash
1414
abp add-package Volo.Abp.Caching
1515
```
1616

@@ -252,6 +252,14 @@ ABP's distributed cache interfaces provide methods to perform batch methods thos
252252

253253
> These are not standard methods of the ASP.NET Core caching. So, some providers may not support them. They are supported by the [ABP Redis Cache integration package](Redis-Cache.md). If the provider doesn't support, it fallbacks to `SetAsync` and `GetAsync` ... methods (called once for each item).
254254
255+
## Caching Entities
256+
257+
ABP Framework provides a [Distributed Entity Cache System](Entity-Cache.md) for caching entities. It is useful if you want to use caching for quicker access to the entity rather than repeatedly querying it from the database.
258+
259+
It's designed as read-only and automatically invalidates a cached entity if the entity is updated or deleted.
260+
261+
> See [Entity Cache](Entity-Cache.md) documentation for more information.
262+
255263
## Advanced Topics
256264

257265
### Unit Of Work Level Cache
@@ -272,4 +280,5 @@ You can [replace](Dependency-Injection.md) this service by your own implementati
272280

273281
## See Also
274282

283+
* [Entity Cache](Entity-Cache.md)
275284
* [Redis Cache](Redis-Cache.md)

docs/en/Deployment/Clustered-Environment.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ The [Database BLOB provider](../Blob-Storing-Database) is the easiest way since
6363

6464
> [ABP Commercial](https://commercial.abp.io/) startup solution templates come with the database BLOB provider as pre-installed, and stores BLOBs in the application's database.
6565
66-
Check the [BLOB Storing](../Blob-Storing.md) document to see all the available BLOG storage providers.
66+
Check the [BLOB Storing](../Blob-Storing.md) document to see all the available BLOB storage providers.
6767

6868
## Configuring Background Jobs
6969

docs/en/Entities.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,14 @@ All these base classes also have non-generic versions to take `AuditedEntity` an
316316

317317
All these base classes also have `...WithUser` pairs, like `FullAuditedAggregateRootWithUser<TUser>` and `FullAuditedAggregateRootWithUser<TKey, TUser>`. This makes possible to add a navigation property to your user entity. However, it is not a good practice to add navigation properties between aggregate roots, so this usage is not suggested (unless you are using an ORM, like EF Core, that well supports this scenario and you really need it - otherwise remember that this approach doesn't work for NoSQL databases like MongoDB where you must truly implement the aggregate pattern). Also, if you add navigation properties to the AppUser class that comes with the startup template, consider to handle (ignore/map) it on the migration dbcontext (see [the EF Core migration document](Entity-Framework-Core-Migrations.md)).
318318

319+
## Caching Entities
320+
321+
ABP Framework provides a [Distributed Entity Cache System](Entity-Cache.md) for caching entities. It is useful if you want to use caching for quicker access to the entity rather than repeatedly querying it from the database.
322+
323+
It's designed as read-only and automatically invalidates a cached entity if the entity is updated or deleted.
324+
325+
> See [Entity Cache](Entity-Cache.md) documentation for more information.
326+
319327
## Extra Properties
320328

321329
ABP defines the `IHasExtraProperties` interface that can be implemented by an entity to be able to dynamically set and get properties for the entity. `AggregateRoot` base class already implements the `IHasExtraProperties` interface. If you've derived from this class (or one of the related audit class defined above), you can directly use the API.

docs/en/Entity-Cache.md

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
# Entity Cache
2+
3+
ABP Framework provides **Distributed Entity Caching System** for caching entities.
4+
5+
You can use this caching mechanism if you want to cache your entity objects automatically and retrieve them from a cache instead of querying it from a database repeatedly.
6+
7+
## How Distributed Entity Caching System Works?
8+
9+
ABP's Entity Caching System does the following operations on behalf of you:
10+
11+
* It gets the entity from the database (by using the [Repositories](Repositories.md)) in its first call and then gets from the cache in subsequent calls.
12+
* It automatically invalidates the cached entity if the entity is updated or deleted. Thus, it will be retrieved from the database in the next call and will be re-cached.
13+
* It uses the cache class's **FullName** as a cache name by default. You can use the `CacheName` attribute on the cache item class to set the cache name.
14+
15+
## Installation
16+
17+
[Volo.Abp.Caching](https://www.nuget.org/packages/Volo.Abp.Caching) is the main package for the ABP's caching system and it's already installed in [the application startup template](Startup-Templates/Index.md). So, you don't need to install it manually.
18+
19+
## Usage
20+
21+
`IEntityCache<TEntityCacheItem, TKey>` is a simple service provided by the ABP Framework for caching entities. It's designed as read-only and contains two methods: `FindAsync` and `GetAsync`.
22+
23+
### Caching Entities
24+
25+
**Example: `Product` entity**
26+
27+
```csharp
28+
[CacheName("Products")]
29+
public class Product : AggregateRoot<Guid>
30+
{
31+
public string Name { get; set; }
32+
public string Description { get; set; }
33+
public float Price { get; set; }
34+
public int StockCount { get; set; }
35+
}
36+
```
37+
38+
* This example uses the `CacheName` attribute for the `Product` class to set the cache name. By default, the cache class's **FullName** is used for the cache name.
39+
40+
If you want to cache this entity, first you should configure the [dependency injection](Dependency-Injection.md) to register the `IEntityCache` service in the `ConfigureServices` method of your [module class](Module-Development-Basics.md):
41+
42+
```csharp
43+
context.Services.AddEntityCache<Product, Guid>();
44+
```
45+
46+
Then configure the [object mapper](https://docs.abp.io/en/abp/latest/Object-To-Object-Mapping) (for `Product` to `ProductDto` mapping):
47+
48+
```csharp
49+
public class MyProjectNameAutoMapperProfile : Profile
50+
{
51+
public MyProjectNameAutoMapperProfile()
52+
{
53+
//other mappings...
54+
55+
CreateMap<Product, ProductDto>();
56+
}
57+
}
58+
```
59+
60+
Now you can inject the `IEntityCache<Product, Guid>` service wherever you need:
61+
62+
```csharp
63+
public class ProductAppService : ApplicationService, IProductAppService
64+
{
65+
private readonly IEntityCache<Product, Guid> _productCache;
66+
67+
public ProductAppService(IEntityCache<Product, Guid> productCache)
68+
{
69+
_productCache = productCache;
70+
}
71+
72+
public async Task<ProductDto> GetAsync(Guid id)
73+
{
74+
var product = await _productCache.GetAsync(id);
75+
return ObjectMapper.Map<Product, ProductDto>(product);
76+
}
77+
}
78+
```
79+
80+
* Here, we've directly cached the `Product` entity. In that case, the `Product` class must be serializable. Sometimes this might not be possible and you may want to use another class to store the cache data. For example, we may want to use the `ProductDto` class instead of the `Product` class for the cached object if the `Product` entity is not serializable.
81+
82+
### Caching Cache Item Classes
83+
84+
`IEntityCache<TEntity, TEntityCacheItem, TKey>` service can be used for caching other cache item classes if the entity is not serializable.
85+
86+
**Example: `ProductDto` class**
87+
88+
```csharp
89+
public class ProductDto : EntityDto<Guid>
90+
{
91+
public string Name { get; set; }
92+
public string Description { get; set; }
93+
public float Price { get; set; }
94+
public int StockCount { get; set; }
95+
}
96+
```
97+
98+
Register the entity cache services to [dependency injection](Dependency-Injection.md) in the `ConfigureServices` method of your [module class](Module-Development-Basics.md):
99+
100+
```csharp
101+
context.Services.AddEntityCache<Product, ProductDto, Guid>();
102+
```
103+
104+
Configure the [object mapper](https://docs.abp.io/en/abp/latest/Object-To-Object-Mapping) (for `Product` to `ProductDto` mapping):
105+
106+
```csharp
107+
public class MyProjectNameAutoMapperProfile : Profile
108+
{
109+
public MyProjectNameAutoMapperProfile()
110+
{
111+
//other mappings...
112+
113+
CreateMap<Product, ProductDto>();
114+
}
115+
}
116+
```
117+
118+
Then, you can inject the `IEntityCache<ProductDto, Guid>` service wherever you want:
119+
120+
```csharp
121+
public class ProductAppService : ApplicationService, IProductAppService
122+
{
123+
private readonly IEntityCache<ProductDto, Guid> _productCache;
124+
125+
public ProductAppService(IEntityCache<ProductDto, Guid> productCache)
126+
{
127+
_productCache = productCache;
128+
}
129+
130+
public async Task<ProductDto> GetAsync(Guid id)
131+
{
132+
return await _productCache.GetAsync(id);
133+
}
134+
}
135+
```
136+
137+
## Configurations
138+
139+
### Registering the Entity Cache Services
140+
141+
You can use one of the `AddEntityCache` methods to register entity cache services to the [Dependency Injection](Dependency-Injection.md) system.
142+
143+
```csharp
144+
public override void ConfigureServices(ServiceConfigurationContext context)
145+
{
146+
var configuration = context.Services.GetConfiguration();
147+
148+
//other configurations...
149+
150+
//directly cache the entity object (Basket)
151+
context.Services.AddEntityCache<Basket, Guid>();
152+
153+
//cache the ProductDto class
154+
context.Services.AddEntityCache<Product, ProductDto, Guid>();
155+
}
156+
```
157+
158+
* You can register entity cache by using the `context.Services.AddEntityCache<TEntity, TKey>()` method for directly cache the entity object.
159+
* Or alternatively, you can use the `context.Services.AddEntityCache<TEntity, TEntityCacheItem, TKey>()` method to configure entities that are mapped to a cache item.
160+
161+
### Caching Options
162+
163+
All of the `context.Services.AddEntityCache()` methods get an optional `DistributedCacheEntryOptions` parameter where you can easily configure the caching options:
164+
165+
```csharp
166+
context.Services.AddEntityCache<Product, ProductDto, Guid>(
167+
new DistributedCacheEntryOptions
168+
{
169+
SlidingExpiration = TimeSpan.FromMinutes(30)
170+
}
171+
);
172+
```
173+
174+
> The default cache duration is **2 minutes** with the `AbsoluteExpirationRelativeToNow` configuration and by configuring the `DistributedCacheEntryOptions` you can change it easily.
175+
176+
## Additonal Notes
177+
178+
* Entity classes should be serializable/deserializable to/from JSON to be cached (because it's serialized to JSON when saving in the [Distributed Cache](Caching.md)). If your entity class is not serializable, you can consider using a cache-item/DTO class instead, as mentioned in the *Usage* section above.
179+
* Entity Caching System is designed as **read-only**. So, you shouldn't make changes to the same entity when you use the entity cache. Instead, you should always read it from the database to ensure transactional consistency.
180+
181+
## See Also
182+
183+
* [Caching](Caching.md)

docs/en/docs-nav.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,10 @@
193193
"text": "Caching",
194194
"path": "Caching.md",
195195
"items": [
196+
{
197+
"text": "Entity Cache",
198+
"path": "Entity-Cache.md"
199+
},
196200
{
197201
"text": "Redis Cache",
198202
"path": "Redis-Cache.md"

0 commit comments

Comments
 (0)