Brief introduction
The ABP provides a cache interface that is used internally by this cache interface. Although the default implementation of an interface is memorycache, it can be used with any other implemented cache provider. Abp.rediscache Pack Redis implements the cache (see "Redis Cache Integration" below).
Icachemanager
The primary interface for caching is Icachemanager. We can inject it and use it to get a cache, such as:
Public classtestappservice:applicationservice{Private ReadOnlyIcachemanager _cachemanager; PublicTestappservice (Icachemanager cachemanager) {_cachemanager=CacheManager; } PublicItem GetItem (intID) {//Try to get from cache return_cachemanager. GetCache ("Mycache") . Get (ID. ToString (), ()= = Getfromdatabase (ID)) asItem; } PublicItem Getfromdatabase (intID) {//... retrieve item from database }}
In this example, we inject icachemanager and get a cache called Mycache.
Warning: GetCache method
If your class is not a singleton, do not use GetCache in your constructor, or you may destroy your cache.
ICache
The Icachemanager.getcache method returns a Icache. One cache is singleton (each cache name). The first time the request is created, and then the same cached object is returned. So, we can share the same cache in different classes (clients) with the same name.
In the sample code, we see the simple use of the Icache.get method. It has two parameters:
Key: A string, required, of a cache entry's keys.
Factory: An action (behavior) that is called when the cache entry for the specified key is not found, and the factory method should create and return a real entry, if the cache of the specified key already exists, it is not called.
The Icache interface also resembles Getordefault, Set, remove, and clear. There is also an async version.
Itypedcache
The Icache interface is a string key and the value is the object type. The Itypedcache is packaged with Icache and provides type-safe, generic. We can use the generic GetCache extension method to get a itypedcache:
itypedcache<int, item> mycache = _cachemanager.getcache<int, item> (" Mycache");
Similarly, we can also use the astyped extension method to convert an existing Icache instance into Itypedcache.
Configuration
The default cache timeout is 60 minutes and it can be changed. If you do not use the items in the cache for more than 60 minutes, they are automatically removed from the cache. You can configure the specified cache or all of the caches.
// Configuration for all caches Configuration.Caching.ConfigureAll (cache ={ = timespan.fromhours (2);}); // Configuration for a specific cache Configuration.Caching.Configure ("mycache", cache = = Timespan.fromhours (8);});
This code should be written in your module's Preinitialize method, with this code, Mycache will have a 8-hour timeout, the other cache has 2 hours.
The first time you create the cache (on the first request) call your configuration behavior. Configuration is not limited to defaultslidingexpiretime, because the cache object is a icache, so you can use its properties and methods, free configuration and initialization.
Entity Cache
Although the ABP cache system is for common purposes, there is a entitycache base class that can help you cache entities. If we get the entities through their IDs, we can cache them with this base class, so we don't have to query from the database more frequently. Let's say we have a person entity that looks like this:
Public class person:entity{ publicstringgetset;} Public int Get Set ; }}
And assume that we already know the ID, to get the name very frequently. First, we need to create a class to cache the entry:
[Automapfrom (typeof(person))] Public class personcacheitem{ publicstringgetset;}
We should not store entities directly in the cache, because caches may need to serialize cache objects, and entities do not necessarily serialize (especially those with navigation properties). That's why we create a simple (like DTO: Data Transfer Object) class that stores data. Add the Automapfrom attribute, which automatically converts a person to a Personcacheitem object. If we do not use Automapfrom, we should manually convert/map for the Maptocacheitem method of overloading the Entitycache class.
Although not required, we may want to define an interface for our cache class:
Public Interface ientitycache<personcacheitem> {}
Finally, we can create a cache class for the entity:
Public class Entitycache<person, personcacheitem> itransientdependency{ public personcache (Icachemanager CacheManager, Irepository<person> repository) base(CacheManager, repository) { }}
That's all the code, and our person cache is already available. A cache class can be temporary (such as an example) or a monomer, which is not to say that the cached data is temporary, and that it is always global and thread-safe in your application.
Now, any name that requires person, we can get from the cache with the ID of the person, using the person cache example as follows:
Public classmypersonservice:itransientdependency{Private ReadOnlyIpersoncache _personcache; PublicMypersonservice (ipersoncache personcache) {_personcache=Personcache; } Public stringGetpersonnamebyid (intID) { return _personcache[id]. Name; //Alternative: _personcache.get (ID). Name; }}
We simply inject Ipersoncache, get the cache entry, and get the Name property.
How the Entitycache works
- In the first call gets the entity from the repository (from the database) and then gets it from the cache in the next call.
- If an entity is updated or deleted, it automatically invalidates the cache, so it will be retrieved from the database again in the next call.
- With Iobjectmapper mapping to cache entries, the Autompper module implements Iobjectmapper, so automapper modules are required. You can overload the Maptocacheitem method to manually map entities to cache entries.
- You can change the cache name by passing a cache name to the base constructor.
- is thread-safe.
If you need more complex caching techniques, you can extend the Entitycache or create your own solution.
Redis Cache Integration
The default cache management uses a memory cache. So, if you have multiple concurrent Web servers using the same application, it can be a problem, in which case you need a distributed/centralized cache service, and you can simply use Redis as your cache server.
First, you'll install the Abp.rediscache NuGet package in your app (for example, you can install it in your Web project). Then add the DependsOn attribute to Abprediscachemodule and then call the Useredis extension method in your module's pre-initialization method. As shown below:
//... other namespaces using Abp.Runtime.Caching.Redis; namespacemyproject.abpzerotemplate.web{[DependsOn (//... other module dependencies typeof(Abprediscachemodule))] Public classMyprojectwebmodule:abpmodule { Public Override voidpreinitialize () {//... other configurations Configuration.Caching.UseRedis (); } //. . Other code }}
The Abp.rediscache package uses "localhost" as the default connection string, and you can add a connection string to the configuration file to rewrite it, for example:
<add name="Abp.Redis.Cache" connectionstring="localhost" />
Similarly, you can add a database ID for Redis to appsettings, for example:
<add key="Abp.Redis.Cache.DatabaseId " value="2" />
Different database IDs, on the same server, help create different key spaces (stand-alone cache).
The Useredis method also has an overload that sets the option value directly (overridden in the configuration file) with the given action (behavior).
For more information about Redis and its configuration, see the Redis documentation.
Reminder: Redis server should be installed and running in ABP.
<<ABP Frames >> Caches