diff --git a/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj b/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj
index 6ce669a75b..01bb10de40 100644
--- a/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj
+++ b/src/Volo.Abp.Caching/Volo.Abp.Caching.csproj
@@ -18,6 +18,7 @@
+
diff --git a/src/Volo.Abp.Caching/Volo/Abp/Caching/AbpCachingModule.cs b/src/Volo.Abp.Caching/Volo/Abp/Caching/AbpCachingModule.cs
index 0274b2db8c..a1b9adbbb3 100644
--- a/src/Volo.Abp.Caching/Volo/Abp/Caching/AbpCachingModule.cs
+++ b/src/Volo.Abp.Caching/Volo/Abp/Caching/AbpCachingModule.cs
@@ -1,5 +1,6 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
+using Volo.Abp.MultiTenancy;
using Volo.Abp.Serialization;
using Volo.Abp.Threading;
@@ -7,6 +8,7 @@ namespace Volo.Abp.Caching
{
[DependsOn(typeof(AbpThreadingModule))]
[DependsOn(typeof(AbpSerializationModule))]
+ [DependsOn(typeof(AbpMultiTenancyAbstractionsModule))]
public class AbpCachingModule : AbpModule
{
public override void ConfigureServices(IServiceCollection services)
diff --git a/src/Volo.Abp.Caching/Volo/Abp/Caching/CacheNameAttribute.cs b/src/Volo.Abp.Caching/Volo/Abp/Caching/CacheNameAttribute.cs
new file mode 100644
index 0000000000..6c8a6d4bee
--- /dev/null
+++ b/src/Volo.Abp.Caching/Volo/Abp/Caching/CacheNameAttribute.cs
@@ -0,0 +1,16 @@
+using JetBrains.Annotations;
+
+namespace Volo.Abp.Caching
+{
+ public class CacheNameAttribute
+ {
+ public string Name { get; }
+
+ public CacheNameAttribute([NotNull] string name)
+ {
+ Check.NotNull(name, nameof(name));
+
+ Name = name;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs b/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs
index e430a04d5e..96486afbfa 100644
--- a/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs
+++ b/src/Volo.Abp.Caching/Volo/Abp/Caching/DistributedCache.cs
@@ -1,7 +1,9 @@
using System;
+using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Distributed;
+using Volo.Abp.MultiTenancy;
using Volo.Abp.Serialization;
using Volo.Abp.Threading;
@@ -10,23 +12,35 @@ namespace Volo.Abp.Caching
public class DistributedCache : IDistributedCache
where TCacheItem : class
{
+ protected string CacheName { get; set; }
+
+ protected bool IgnoreMultiTenancy { get; set; }
+
protected IDistributedCache Cache { get; }
+
protected ICancellationTokenProvider CancellationTokenProvider { get; }
+
protected IObjectSerializer ObjectSerializer { get; }
+ protected ICurrentTenant CurrentTenant { get; }
+
public DistributedCache(
IDistributedCache cache,
ICancellationTokenProvider cancellationTokenProvider,
- IObjectSerializer objectSerializer)
+ IObjectSerializer objectSerializer,
+ ICurrentTenant currentTenant)
{
Cache = cache;
CancellationTokenProvider = cancellationTokenProvider;
ObjectSerializer = objectSerializer;
+ CurrentTenant = currentTenant;
+
+ SetDefaultOptions();
}
- public TCacheItem Get(string key)
+ public virtual TCacheItem Get(string key)
{
- var cachedBytes = Cache.Get(key);
+ var cachedBytes = Cache.Get(NormalizeKey(key));
if (cachedBytes == null)
{
return null;
@@ -35,9 +49,9 @@ namespace Volo.Abp.Caching
return ObjectSerializer.Deserialize(cachedBytes);
}
- public async Task GetAsync(string key, CancellationToken token = default)
+ public virtual async Task GetAsync(string key, CancellationToken token = default)
{
- var cachedBytes = await Cache.GetAsync(key, CancellationTokenProvider.FallbackToProvider(token));
+ var cachedBytes = await Cache.GetAsync(NormalizeKey(key), CancellationTokenProvider.FallbackToProvider(token));
if (cachedBytes == null)
{
return null;
@@ -46,43 +60,69 @@ namespace Volo.Abp.Caching
return ObjectSerializer.Deserialize(cachedBytes);
}
- public void Set(string key, TCacheItem value, DistributedCacheEntryOptions options)
+ public virtual void Set(string key, TCacheItem value, DistributedCacheEntryOptions options)
{
Cache.Set(
- key,
+ NormalizeKey(key),
ObjectSerializer.Serialize(value),
options ?? new DistributedCacheEntryOptions { SlidingExpiration = TimeSpan.FromMinutes(20) } //TODO: implement per cache item and global defaults!!!
);
}
- public Task SetAsync(string key, TCacheItem value, DistributedCacheEntryOptions options = null, CancellationToken token = default)
+ public virtual Task SetAsync(string key, TCacheItem value, DistributedCacheEntryOptions options = null, CancellationToken token = default)
{
return Cache.SetAsync(
- key,
+ NormalizeKey(key),
ObjectSerializer.Serialize(value),
options ?? new DistributedCacheEntryOptions { SlidingExpiration = TimeSpan.FromMinutes(20) }, //TODO: implement per cache item and global defaults!!!
CancellationTokenProvider.FallbackToProvider(token)
);
}
- public void Refresh(string key)
+ public virtual void Refresh(string key)
+ {
+ Cache.Refresh(NormalizeKey(key));
+ }
+
+ public virtual Task RefreshAsync(string key, CancellationToken token = default)
{
- Cache.Refresh(key);
+ return Cache.RefreshAsync(NormalizeKey(key), CancellationTokenProvider.FallbackToProvider(token));
}
- public Task RefreshAsync(string key, CancellationToken token = default)
+ public virtual void Remove(string key)
{
- return Cache.RefreshAsync(key, CancellationTokenProvider.FallbackToProvider(token));
+ Cache.Remove(NormalizeKey(key));
}
- public void Remove(string key)
+ public virtual Task RemoveAsync(string key, CancellationToken token = default)
{
- Cache.Remove(key);
+ return Cache.RemoveAsync(NormalizeKey(key), CancellationTokenProvider.FallbackToProvider(token));
}
- public Task RemoveAsync(string key, CancellationToken token = default)
+ protected virtual string NormalizeKey(string key)
{
- return Cache.RemoveAsync(key, CancellationTokenProvider.FallbackToProvider(token));
+ var normalizedKey = "c:" + CacheName + ",k:" + key;
+
+ if (!IgnoreMultiTenancy && CurrentTenant.Id.HasValue)
+ {
+ normalizedKey = "t:" + CurrentTenant.Id.Value + "," + normalizedKey;
+ }
+
+ return normalizedKey;
+ }
+
+ protected virtual void SetDefaultOptions()
+ {
+ //CacheName
+ var cacheNameAttribute = typeof(TCacheItem)
+ .GetCustomAttributes(true)
+ .OfType()
+ .FirstOrDefault();
+
+ CacheName = cacheNameAttribute != null ? cacheNameAttribute.Name : typeof(TCacheItem).Name;
+
+ //IgnoreMultiTenancy
+ IgnoreMultiTenancy = typeof(TCacheItem).IsDefined(typeof(IgnoreMultiTenancyAttribute), true);
}
}
}
\ No newline at end of file
diff --git a/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/IgnoreMultiTenancy.cs b/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/IgnoreMultiTenancy.cs
new file mode 100644
index 0000000000..c4ffdaa081
--- /dev/null
+++ b/src/Volo.Abp.MultiTenancy.Abstractions/Volo/Abp/MultiTenancy/IgnoreMultiTenancy.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Volo.Abp.MultiTenancy
+{
+ [AttributeUsage(AttributeTargets.All)]
+ public class IgnoreMultiTenancyAttribute : Attribute
+ {
+
+ }
+}