diff --git a/sample/EasyCaching.Demo.HybridCache/Controllers/ValuesController.cs b/sample/EasyCaching.Demo.HybridCache/Controllers/ValuesController.cs
index 0c284855..3360c753 100644
--- a/sample/EasyCaching.Demo.HybridCache/Controllers/ValuesController.cs
+++ b/sample/EasyCaching.Demo.HybridCache/Controllers/ValuesController.cs
@@ -1,10 +1,10 @@
namespace EasyCaching.Demo.HybridCache.Controllers
-{
- using EasyCaching.HybridCache;
+{
+ using EasyCaching.Core;
using Microsoft.AspNetCore.Mvc;
- using System;
- using System.Threading.Tasks;
-
+ using System;
+ using System.Threading.Tasks;
+
[Route("api/[controller]")]
public class ValuesController : Controller
{
diff --git a/src/EasyCaching.Core/IEasyCachingProvider.cs b/src/EasyCaching.Core/IEasyCachingProvider.cs
index 2a65fe8c..e6e248d9 100644
--- a/src/EasyCaching.Core/IEasyCachingProvider.cs
+++ b/src/EasyCaching.Core/IEasyCachingProvider.cs
@@ -114,5 +114,17 @@ public interface IEasyCachingProvider
/// Expiration.
/// The 1st type parameter.
Task RefreshAsync(string cacheKey, T cacheValue, TimeSpan expiration) where T : class;
+
+ ///
+ /// Removes cached item by cachekey's prefix.
+ ///
+ /// Prefix of CacheKey.
+ void RemoveByPrefix(string prefix);
+
+ ///
+ /// Removes cached item by cachekey's prefix async.
+ ///
+ /// Prefix of CacheKey.
+ Task RemoveByPrefixAsync(string prefix);
}
}
diff --git a/src/EasyCaching.Core/IHybridCachingProvider.cs b/src/EasyCaching.Core/IHybridCachingProvider.cs
new file mode 100644
index 00000000..44d2ff79
--- /dev/null
+++ b/src/EasyCaching.Core/IHybridCachingProvider.cs
@@ -0,0 +1,7 @@
+namespace EasyCaching.Core
+{
+ ///
+ /// Hybrid caching provider.
+ ///
+ public interface IHybridCachingProvider : IEasyCachingProvider { }
+}
diff --git a/src/EasyCaching.HybridCache/HybridCacheServiceCollectionExtensions.cs b/src/EasyCaching.HybridCache/HybridCacheServiceCollectionExtensions.cs
index 123b916b..b6ac9599 100644
--- a/src/EasyCaching.HybridCache/HybridCacheServiceCollectionExtensions.cs
+++ b/src/EasyCaching.HybridCache/HybridCacheServiceCollectionExtensions.cs
@@ -1,5 +1,6 @@
namespace EasyCaching.HybridCache
{
+ using EasyCaching.Core;
using EasyCaching.Core.Internal;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
diff --git a/src/EasyCaching.HybridCache/HybridCachingProvider.cs b/src/EasyCaching.HybridCache/HybridCachingProvider.cs
index 9e182b67..6406a9df 100644
--- a/src/EasyCaching.HybridCache/HybridCachingProvider.cs
+++ b/src/EasyCaching.HybridCache/HybridCachingProvider.cs
@@ -5,11 +5,6 @@
using System;
using System.Threading.Tasks;
- ///
- /// Hybrid caching provider.
- ///
- public interface IHybridCachingProvider : IEasyCachingProvider{}
-
///
/// Hybrid caching provider.
///
@@ -331,5 +326,15 @@ public async Task RefreshAsync(string cacheKey, T cacheValue, TimeSpan expira
await this.RemoveAsync(cacheKey);
await this.SetAsync(cacheKey, cacheValue, expiration);
}
+
+ public void RemoveByPrefix(string prefix)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Task RemoveByPrefixAsync(string prefix)
+ {
+ throw new NotImplementedException();
+ }
}
}
diff --git a/src/EasyCaching.InMemory/InMemoryCachingProvider.cs b/src/EasyCaching.InMemory/InMemoryCachingProvider.cs
index 1e21f246..541144c0 100644
--- a/src/EasyCaching.InMemory/InMemoryCachingProvider.cs
+++ b/src/EasyCaching.InMemory/InMemoryCachingProvider.cs
@@ -247,5 +247,15 @@ public async Task RefreshAsync(string cacheKey, T cacheValue, TimeSpan expira
await this.RemoveAsync(cacheKey);
await this.SetAsync(cacheKey, cacheValue, expiration);
}
+
+ public void RemoveByPrefix(string prefix)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Task RemoveByPrefixAsync(string prefix)
+ {
+ throw new NotImplementedException();
+ }
}
}
diff --git a/src/EasyCaching.Memcached/DefaultMemcachedCachingProvider.cs b/src/EasyCaching.Memcached/DefaultMemcachedCachingProvider.cs
index 4a687473..d0876868 100644
--- a/src/EasyCaching.Memcached/DefaultMemcachedCachingProvider.cs
+++ b/src/EasyCaching.Memcached/DefaultMemcachedCachingProvider.cs
@@ -251,5 +251,15 @@ public async Task RefreshAsync(string cacheKey, T cacheValue, TimeSpan expira
await this.RemoveAsync(cacheKey);
await this.SetAsync(cacheKey, cacheValue, expiration);
}
+
+ public void RemoveByPrefix(string prefix)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Task RemoveByPrefixAsync(string prefix)
+ {
+ throw new NotImplementedException();
+ }
}
}
diff --git a/src/EasyCaching.Redis/DefaultRedisCachingProvider.cs b/src/EasyCaching.Redis/DefaultRedisCachingProvider.cs
index be8b0bd7..94886aee 100644
--- a/src/EasyCaching.Redis/DefaultRedisCachingProvider.cs
+++ b/src/EasyCaching.Redis/DefaultRedisCachingProvider.cs
@@ -4,6 +4,8 @@
using EasyCaching.Core.Internal;
using StackExchange.Redis;
using System;
+ using System.Collections.Generic;
+ using System.Linq;
using System.Threading.Tasks;
///
@@ -16,6 +18,11 @@ public class DefaultRedisCachingProvider : IEasyCachingProvider
///
private readonly IDatabase _cache;
+ ///
+ /// The servers.
+ ///
+ private readonly IEnumerable _servers;
+
///
/// The db provider.
///
@@ -28,7 +35,7 @@ public class DefaultRedisCachingProvider : IEasyCachingProvider
///
///
- /// is not distributed cache.
+ /// is distributed cache.
///
public bool IsDistributedCache => false;
@@ -47,6 +54,7 @@ public DefaultRedisCachingProvider(
_dbProvider = dbProvider;
_serializer = serializer;
_cache = _dbProvider.GetDatabase();
+ _servers = _dbProvider.GetServerList();
}
///
@@ -279,5 +287,109 @@ public async Task RefreshAsync(string cacheKey, T cacheValue, TimeSpan expira
await this.RemoveAsync(cacheKey);
await this.SetAsync(cacheKey, cacheValue, expiration);
}
+
+ ///
+ /// Removes cached item by cachekey's prefix.
+ ///
+ /// Prefix of CacheKey.
+ public void RemoveByPrefix(string prefix)
+ {
+ ArgumentCheck.NotNullOrWhiteSpace(prefix, nameof(prefix));
+
+ this.HandlePrefix(prefix);
+
+ foreach (var server in _servers)
+ {
+ this.HandleKeyDelWithTran(server, prefix);
+ }
+ }
+
+ ///
+ /// Removes cached item by cachekey's prefix async.
+ ///
+ /// Prefix of CacheKey.
+ public async Task RemoveByPrefixAsync(string prefix)
+ {
+ ArgumentCheck.NotNullOrWhiteSpace(prefix, nameof(prefix));
+
+ this.HandlePrefix(prefix);
+
+ foreach (var server in _servers)
+ {
+ await this.HandleKeyDelWithTranAsync(server, prefix);
+ }
+ }
+
+ ///
+ /// Delete keys of Redis using transaction.
+ ///
+ /// Server.
+ /// Prefix.
+ private void HandleKeyDelWithTran(IServer server, string prefix)
+ {
+ int count = 1;
+ do
+ {
+ var keys = server.Keys(pattern: prefix, pageSize: 100);
+ count = keys.Count();
+ if (count > 0)
+ {
+ var tran = _cache.CreateTransaction();
+
+ tran.KeyDeleteAsync(keys.ToArray());
+
+ tran.Execute(CommandFlags.FireAndForget);
+ }
+ }
+ while (count <= 0);
+ }
+
+ ///
+ /// Delete keys of Redis using transaction async.
+ ///
+ /// The key del with tran async.
+ /// Server.
+ /// Prefix.
+ private async Task HandleKeyDelWithTranAsync(IServer server, string prefix)
+ {
+ int count = 1;
+ do
+ {
+ var keys = server.Keys(pattern: prefix, pageSize: 100);
+ count = keys.Count();
+ if (count > 0)
+ {
+ var tran = _cache.CreateTransaction();
+
+ await tran.KeyDeleteAsync(keys.ToArray());
+
+ await tran.ExecuteAsync(CommandFlags.FireAndForget);
+ }
+ }
+ while (count <= 0);
+ }
+
+ ///
+ /// Handles the prefix of CacheKey.
+ ///
+ /// Prefix of CacheKey.
+ ///
+ private void HandlePrefix(string prefix)
+ {
+ // Forbid
+ if (prefix.Equals("*"))
+ {
+ throw new ArgumentException("the prefix should not to *");
+ }
+
+ // Don't start with *
+ prefix = new System.Text.RegularExpressions.Regex("^\\*+").Replace(prefix, "");
+
+ // End with *
+ if (!prefix.EndsWith("*", StringComparison.OrdinalIgnoreCase))
+ {
+ prefix = string.Concat(prefix, "*");
+ }
+ }
}
}
diff --git a/src/EasyCaching.SQLite/ConstSQL.cs b/src/EasyCaching.SQLite/ConstSQL.cs
index ec8b0e3a..88a6755e 100644
--- a/src/EasyCaching.SQLite/ConstSQL.cs
+++ b/src/EasyCaching.SQLite/ConstSQL.cs
@@ -31,6 +31,11 @@ FROM [easycaching]
///
public const string REMOVESQL = @"DELETE FROM [easycaching] WHERE [cachekey] = @cachekey ";
+ ///
+ /// The removebyprefixsql.
+ ///
+ public const string REMOVEBYPREFIXSQL = @"DELETE FROM [easycaching] WHERE [cachekey] like @cachekey ";
+
///
/// The existssql.
///
diff --git a/src/EasyCaching.SQLite/SQLiteCachingProvider.cs b/src/EasyCaching.SQLite/SQLiteCachingProvider.cs
index 90e21886..fbc1e640 100644
--- a/src/EasyCaching.SQLite/SQLiteCachingProvider.cs
+++ b/src/EasyCaching.SQLite/SQLiteCachingProvider.cs
@@ -302,5 +302,27 @@ public async Task RefreshAsync(string cacheKey, T cacheValue, TimeSpan expira
await this.RemoveAsync(cacheKey);
await this.SetAsync(cacheKey, cacheValue, expiration);
}
+
+ ///
+ /// Removes cached item by cachekey's prefix.
+ ///
+ /// Prefix of CacheKey.
+ public void RemoveByPrefix(string prefix)
+ {
+ ArgumentCheck.NotNullOrWhiteSpace(prefix, nameof(prefix));
+
+ _cache.Execute(ConstSQL.REMOVEBYPREFIXSQL, new { cachekey = string.Concat(prefix, "%") });
+ }
+
+ ///
+ /// Removes cached item by cachekey's prefix async.
+ ///
+ /// Prefix of CacheKey.
+ public async Task RemoveByPrefixAsync(string prefix)
+ {
+ ArgumentCheck.NotNullOrWhiteSpace(prefix, nameof(prefix));
+
+ await _cache.ExecuteAsync(ConstSQL.REMOVEBYPREFIXSQL, new { cachekey = string.Concat(prefix ,"%") });
+ }
}
}