Преглед изворни кода

增加全局过滤器缓存处理优化效率 !414

zuohuaijun пре 3 година
родитељ
комит
f3baf0cc66

+ 3 - 5
Admin.NET/Admin.NET.Application/AppConfig.json

@@ -2,20 +2,18 @@
     "$schema": "https://gitee.com/dotnetchina/Furion/raw/net6/schemas/v3/furion-schema.json",
 
     "DbConnection": {
-        "EnableInitTable": false, // 启用初始化库表
+        "EnableInitTable": true, // 启用初始化库表
         "EnableDiffLog": false, // 启用库表差异日志
         "ConnectionConfigs": [ // 默认第一个为主库
             {
                 "ConfigId": "Dilon",
                 "DbType": "Sqlite", // MySql、SqlServer、Sqlite、Oracle、PostgreSQL、Dm、Kdbndp、Oscar、MySqlConnector、Access
-                "ConnectionString": "DataSource=./Admin.NET.db", // DataSource=C:\\db\\Admin.NET.db
-                "IsAutoCloseConnection": true
+                "ConnectionString": "DataSource=./Admin.NET.db"
             },
             {
                 "ConfigId": "Test",
                 "DbType": "Sqlite",
-                "ConnectionString": "DataSource=./Test.db",
-                "IsAutoCloseConnection": true
+                "ConnectionString": "DataSource=./Test.db"
             }
         ]
     },

+ 3 - 1
Admin.NET/Admin.NET.Application/Service/TestService.cs

@@ -59,7 +59,9 @@ public class TestService : IDynamicApiController, ITransient
     public async Task<List<Test>> TestUnitOfWork()
     {
         await _testRep.InsertAsync(new Test() { Name = "admin" });
-        throw new Exception("异常");
+        var a = 1;
+        var b = 0;
+        var c = a / b;
         return await _testRep.GetListAsync();
     }
 

+ 1 - 1
Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj

@@ -36,7 +36,7 @@
     <PackageReference Include="OnceMi.AspNetCore.OSS" Version="1.1.8" />
     <PackageReference Include="SKIT.FlurlHttpClient.Wechat.Api" Version="2.17.0" />
     <PackageReference Include="SKIT.FlurlHttpClient.Wechat.TenpayV3" Version="2.13.0" />
-    <PackageReference Include="SqlSugarCore" Version="5.1.2.7" />
+    <PackageReference Include="SqlSugarCore" Version="5.1.2.8" />
     <PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.20" />
     <PackageReference Include="UAParser" Version="3.1.47" />
     <PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />

+ 7 - 13
Admin.NET/Admin.NET.Core/Admin.NET.Core.xml

@@ -19,12 +19,17 @@
             非实体表特性
             </summary>
         </member>
-        <member name="M:Admin.NET.Core.CSRedisSetup.AddCSRedisSetup(Microsoft.Extensions.DependencyInjection.IServiceCollection)">
+        <member name="M:Admin.NET.Core.CacheSetup.AddCache(Microsoft.Extensions.DependencyInjection.IServiceCollection)">
             <summary>
-            CSRedis初始化
+            缓存注册(Redis缓存)
             </summary>
             <param name="services"></param>
         </member>
+        <member name="T:Admin.NET.Core.SqlSugarCache">
+            <summary>
+            SqlSugar二级缓存
+            </summary>
+        </member>
         <member name="T:Admin.NET.Core.CacheConst">
             <summary>
             缓存相关常量
@@ -7350,11 +7355,6 @@
             <param name="pageSize"></param>
             <returns></returns>
         </member>
-        <member name="T:Admin.NET.Core.SqlSugarQueryFilterCache">
-            <summary>
-            数据过滤器缓存
-            </summary>
-        </member>
         <member name="T:Admin.NET.Core.SqlSugarRepository`1">
             <summary>
             SqlSugar仓储类
@@ -7715,12 +7715,6 @@
             <param name="args"></param>
             <returns></returns>
         </member>
-        <member name="T:Admin.NET.Core.Singleton`1">
-            <summary>
-            单例泛型类
-            </summary>
-            <typeparam name="T"></typeparam>
-        </member>
         <member name="T:Admin.NET.Core.ByteUtil">
             <summary>
             字节数组操作扩展类

+ 0 - 34
Admin.NET/Admin.NET.Core/Cache/CSRedisSetup.cs

@@ -1,34 +0,0 @@
-using CSRedis;
-using Microsoft.Extensions.Caching.Memory;
-using Microsoft.Extensions.Caching.Redis;
-
-namespace Admin.NET.Core;
-
-public static class CSRedisSetup
-{
-    /// <summary>
-    /// CSRedis初始化
-    /// </summary>
-    /// <param name="services"></param>
-    public static void AddCSRedisSetup(this IServiceCollection services)
-    {
-        services.AddSingleton<IDistributedCache>(provider =>
-        {
-            var cacheOptions = App.GetOptions<CacheOptions>();
-            if (cacheOptions.CacheType == CacheTypeEnum.RedisCache.ToString())
-            {
-                var redisStr = $"{cacheOptions.RedisConnectionString},prefix={cacheOptions.InstanceName}";
-
-                var redis = new CSRedisClient(redisStr);
-                RedisHelper.Initialization(redis);
-                return new CSRedisCache(redis);
-            }
-            else // 默认使用内存
-            {
-                services.AddDistributedMemoryCache();
-                IOptions<MemoryDistributedCacheOptions> options = provider.GetService<IOptions<MemoryDistributedCacheOptions>>();
-                return new MemoryDistributedCache(options);
-            }
-        });
-    }
-}

+ 26 - 0
Admin.NET/Admin.NET.Core/Cache/CacheSetup.cs

@@ -0,0 +1,26 @@
+using CSRedis;
+using Microsoft.Extensions.Caching.Redis;
+
+namespace Admin.NET.Core;
+
+public static class CacheSetup
+{
+    /// <summary>
+    /// 缓存注册(Redis缓存)
+    /// </summary>
+    /// <param name="services"></param>
+    public static void AddCache(this IServiceCollection services)
+    {
+        var cacheOptions = App.GetOptions<CacheOptions>();
+        if (cacheOptions.CacheType != CacheTypeEnum.RedisCache.ToString())
+            return;
+
+        services.AddSingleton<IDistributedCache>(provider =>
+        {
+            var redisStr = $"{cacheOptions.RedisConnectionString},prefix={cacheOptions.InstanceName}";
+            var redis = new CSRedisClient(redisStr);
+            RedisHelper.Initialization(redis);
+            return new CSRedisCache(redis);
+        });
+    }
+}

+ 53 - 0
Admin.NET/Admin.NET.Core/Cache/SqlSugarCache.cs

@@ -0,0 +1,53 @@
+namespace Admin.NET.Core;
+
+/// <summary>
+/// SqlSugar二级缓存
+/// </summary>
+public class SqlSugarCache : ICacheService
+{
+    private static IDistributedCache _cache = App.GetService<IDistributedCache>();
+
+    public void Add<V>(string key, V value)
+    {
+        _cache.Set(key, Encoding.UTF8.GetBytes(JSON.Serialize(value)));
+    }
+
+    public void Add<V>(string key, V value, int cacheDurationInSeconds)
+    {
+        _cache.Set(key, Encoding.UTF8.GetBytes(JSON.Serialize(value)), new DistributedCacheEntryOptions() { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(cacheDurationInSeconds) });
+    }
+
+    public bool ContainsKey<V>(string key)
+    {
+        return _cache.Get(key) != null;
+    }
+
+    public V Get<V>(string key)
+    {
+        var res = _cache.Get(key);
+        return res == null ? default : JSON.Deserialize<V>(Encoding.UTF8.GetString(res));
+    }
+
+    public IEnumerable<string> GetAllKey<V>()
+    {
+        const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;
+        var entries = _cache.GetType().GetField("_entries", flags)?.GetValue(_cache);
+        var cacheItems = entries?.GetType().GetProperty("Keys").GetValue(entries) as ICollection<object>;
+        return cacheItems == null ? new List<string>() : cacheItems.Select(u => u.ToString()).ToList();
+    }
+
+    public V GetOrCreate<V>(string cacheKey, Func<V> create, int cacheDurationInSeconds = int.MaxValue)
+    {
+        if (!ContainsKey<V>(cacheKey))
+            return JSON.Deserialize<V>(Encoding.UTF8.GetString(_cache.Get(cacheKey)));
+
+        var result = create();
+        Add(cacheKey, result, cacheDurationInSeconds);
+        return result;
+    }
+
+    public void Remove<V>(string key)
+    {
+        _cache.Remove(key);
+    }
+}

+ 1 - 0
Admin.NET/Admin.NET.Core/Job/OnlineUserJob.cs

@@ -15,6 +15,7 @@ public class OnlineUserJob : ISpareTimeWorker
         {
             var services = scope.ServiceProvider;
             var rep = services.GetService<SqlSugarRepository<SysOnlineUser>>();
+            if (rep == null) return;
             await rep.AsDeleteable().ExecuteCommandAsync();
 
             Console.ForegroundColor = ConsoleColor.Blue;

+ 0 - 18
Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarQueryFilterCache.cs

@@ -1,18 +0,0 @@
-using System.Collections.Concurrent;
-
-namespace Admin.NET.Core;
-
-/// <summary>
-/// 数据过滤器缓存
-/// </summary>
-public class SqlSugarQueryFilterCache : Singleton<SqlSugarQueryFilterCache>
-{
-    private ConcurrentDictionary<string, QueryFilterProvider> _queryEntityFilters = new();
-    
-    // 实体过滤器
-    public ConcurrentDictionary<string, QueryFilterProvider> QueryEntityFilters => _queryEntityFilters;
-
-    private SqlSugarQueryFilterCache()
-    {
-    }
-}

+ 17 - 26
Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs

@@ -18,26 +18,25 @@ public static class SqlSugarSetup
                 if ((type.PropertyType.IsGenericType && type.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
                     || (type.PropertyType == typeof(string) && type.GetCustomAttribute<RequiredAttribute>() == null))
                     column.IsNullable = true;
-            }
+            },
+            DataInfoCacheService = new SqlSugarCache(),
         };
         dbOptions.ConnectionConfigs.ForEach(config =>
         {
             config.ConfigureExternalServices = configureExternalServices;
+            config.InitKeyType = InitKeyType.Attribute;
+            config.IsAutoCloseConnection = true;
+            config.MoreSettings = new ConnMoreSettings
+            {
+                IsAutoRemoveDataCache = true
+            };
         });
 
-        // 是否首次 初始化SqlSugarScope配置
-        var hasInitConfig = false;
-
         SqlSugarScope sqlSugar = new(dbOptions.ConnectionConfigs, db =>
         {
-            //Stopwatch stopWatch = new Stopwatch();
-            //stopWatch.Start();
-
-            var localConfig = hasInitConfig;
             dbOptions.ConnectionConfigs.ForEach(config =>
             {
-                var configId = (string)config.ConfigId;
-                var dbProvider = db.GetConnectionScope(configId);
+                var dbProvider = db.GetConnectionScope((string)config.ConfigId);
 
                 // 设置超时时间
                 dbProvider.Ado.CommandTimeOut = 30;
@@ -124,7 +123,9 @@ public static class SqlSugarSetup
                     Console.WriteLine(DateTime.Now + $"\r\n**********差异日志开始**********\r\n{Environment.NewLine}{JsonConvert.SerializeObject(LogDiff)}{Environment.NewLine}**********差异日志结束**********\r\n");
                 };
 
-                if (!localConfig)
+                // 缓存处理过滤器
+                var queryFilterProvider = db.DataCache.Get<QueryFilterProvider>(config.ConfigId);
+                if (queryFilterProvider == null)
                 {
                     // 配置实体假删除过滤器
                     SetDeletedEntityFilter(dbProvider);
@@ -134,22 +135,12 @@ public static class SqlSugarSetup
                     SetCustomEntityFilter(dbProvider);
                     // 配置租户实体过滤器
                     SetTenantEntityFilter(dbProvider);
-
-                    SqlSugarQueryFilterCache.Instance.QueryEntityFilters.TryAdd(configId,
-                        dbProvider.QueryFilter);
                 }
                 else
                 {
-                    if (SqlSugarQueryFilterCache.Instance.QueryEntityFilters.TryGetValue(configId,
-                           out QueryFilterProvider filter))
-                        dbProvider.QueryFilter = filter;
+                    dbProvider.QueryFilter = queryFilterProvider;
                 }
             });
-
-            //stopWatch.Stop();
-            //long ts = stopWatch.ElapsedMilliseconds;
-
-            hasInitConfig = true;
         });
 
         // 初始化数据库结构及种子数据
@@ -207,10 +198,10 @@ public static class SqlSugarSetup
             if (seedDataTable.Columns.Contains(SqlSugarConst.PrimaryKey))
             {
                 var storage = provider.Storageable(seedDataTable).WhereColumns(SqlSugarConst.PrimaryKey).ToStorage();
-                // 如果添加一条种子数,sqlsugar 默认以 @param 的方式赋值,如果 PropertyType 为空,则默认数据类型为字符串。插入 pgsql 时候会报错,所以要忽略为空的值添加
-                _ = ((InsertableProvider<Dictionary<string, object>>)storage.AsInsertable).IsSingle ?
-                    storage.AsInsertable.IgnoreColumns("UpdateTime", "UpdateUserId", "CreateUserId").ExecuteCommand() :
-                    storage.AsInsertable.ExecuteCommand();
+                //// 如果添加一条种子数,sqlsugar 默认以 @param 的方式赋值,如果 PropertyType 为空,则默认数据类型为字符串。插入 pgsql 时候会报错,所以要忽略为空的值添加
+                //_ = ((InsertableProvider<Dictionary<string, object>>)storage.AsInsertable).IsSingle ?
+                //    storage.AsInsertable.IgnoreColumns("UpdateTime", "UpdateUserId", "CreateUserId").ExecuteCommand() :
+                //    storage.AsInsertable.ExecuteCommand();
                 storage.AsUpdateable.ExecuteCommand();
             }
             else // 没有主键或者不是预定义的主键(没主键有重复的可能)

+ 0 - 26
Admin.NET/Admin.NET.Core/Util/Singleton.cs

@@ -1,26 +0,0 @@
-namespace Admin.NET.Core;
-
-/// <summary>
-/// 单例泛型类
-/// </summary>
-/// <typeparam name="T"></typeparam>
-public abstract class Singleton<T> where T : class
-{
-    private static readonly Lazy<T> _instance
-        = new Lazy<T>(() =>
-        {
-            var ctors = typeof(T).GetConstructors(
-                BindingFlags.Instance
-                | BindingFlags.NonPublic
-                | BindingFlags.Public);
-            if (ctors.Count() != 1)
-                throw new InvalidOperationException($"Type {typeof(T)} must have exactly one constructor.");
-            var ctor = ctors.SingleOrDefault(c => !c.GetParameters().Any() && c.IsPrivate);
-            if (ctor == null)
-                throw new InvalidOperationException(
-                    $"The constructor for {typeof(T)} must be private and take no parameters.");
-            return (T)ctor.Invoke(null);
-        });
-
-    public static T Instance => _instance.Value;
-}

+ 2 - 3
Admin.NET/Admin.NET.Web.Core/Startup.cs

@@ -25,6 +25,8 @@ public class Startup : AppStartup
     {
         // 配置选项
         services.AddProjectOptions();
+        // 缓存注册
+        services.AddCache();
         // SqlSugar
         services.AddSqlSugar();
         // JWT
@@ -105,9 +107,6 @@ public class Startup : AppStartup
             options.UseMailKit(App.GetOptions<EmailOptions>());
         });
 
-        // Redis缓存
-        services.AddCSRedisSetup();
-
         // 模板引擎
         services.AddViewEngine();