Skip to content

Commit c5fe809

Browse files
committed
[feat] 扩展sqlsguar二级缓存
1 parent c855b63 commit c5fe809

File tree

8 files changed

+230
-78
lines changed

8 files changed

+230
-78
lines changed

Ape.Volo.Api/Controllers/Test/TestController.cs

+14-10
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
using System.Threading.Tasks;
33
using Ape.Volo.Api.ActionExtension.Sign;
44
using Ape.Volo.Api.Controllers.Base;
5+
using Ape.Volo.Common.AttributeExt;
6+
using Ape.Volo.Common.Caches;
57
using Ape.Volo.Common.Model;
68
using Ape.Volo.Common.SnowflakeIdHelper;
79
using Ape.Volo.Entity.Test;
@@ -23,14 +25,16 @@ public class TestController : BaseApiController
2325
// //private readonly IEventBus _eventBus;
2426
// private readonly IRedisCacheService _redisCacheService;
2527
private readonly ITestOrderService _testOrderService;
28+
private ICache _cache;
2629

2730
// private readonly IUserService _userService;
2831
// private readonly IRoleService _roleService;
2932
// private readonly IBrowserDetector _browserDetector;
3033

31-
public TestController(ITestOrderService testOrderService)
34+
public TestController(ITestOrderService testOrderService, ICache cache)
3235
{
3336
_testOrderService = testOrderService;
37+
_cache = cache;
3438
//_eventBus = eventBus;
3539
}
3640

@@ -128,17 +132,17 @@ public ActionResult<object> EventBusTry()
128132
[HttpGet]
129133
[Route("SearchOrder")]
130134
[Description("查询")]
135+
[NotAudit]
131136
public async Task<ActionResult<object>> SearchOrder()
132137
{
133-
await _testOrderService.AddEntityAsync(new TestOrder()
134-
{
135-
Id = IdHelper.GetLongId(),
136-
OrderNo = "1001",
137-
GoodsName = "iphone 16",
138-
Qty = 1,
139-
Price = 5000
140-
});
141-
138+
// await _testOrderService.AddEntityAsync(new TestOrder()
139+
// {
140+
// Id = IdHelper.GetLongId(),
141+
// OrderNo = "1001",
142+
// GoodsName = "iphone 16",
143+
// Qty = 1,
144+
// Price = 5000
145+
// });
142146
var list = await _testOrderService.Table.ToListAsync();
143147
return JsonContent(new ActionResultVm<TestOrder>
144148
{

Ape.Volo.Api/Extensions/SqlSugarSetup.cs

+7-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.IO;
44
using System.Linq;
55
using Ape.Volo.Api.Serilog;
6+
using Ape.Volo.Common.Caches.SqlSugar;
67
using Ape.Volo.Common.ConfigOptions;
78
using Ape.Volo.Common.DI;
89
using Ape.Volo.Common.Extensions;
@@ -101,6 +102,9 @@ public static void AddSqlSugarSetup(this IServiceCollection services, Configs co
101102
},
102103
ConfigureExternalServices = new ConfigureExternalServices
103104
{
105+
DataInfoCacheService = configs.CacheOption.RedisCacheSwitch.Enabled
106+
? new SqlSugarRedisCache()
107+
: new SqlSugarDistributedCache(),
104108
EntityService = (c, p) =>
105109
{
106110
p.DbColumnName = UtilMethods.ToUnderLine(p.DbColumnName); //字段使用驼峰转下划线,不需要请注释
@@ -207,7 +211,7 @@ private static void DataExecuting(object value, DataFilterModel entityInfo)
207211
break;
208212
}
209213

210-
var httpUser = AutofacHelper.GetScopeService<IHttpUser>();
214+
var httpUser = AutofacHelper.GetService<IHttpUser>();
211215
if (httpUser.IsNull()) return;
212216
switch (entityInfo.OperationType)
213217
{
@@ -257,7 +261,7 @@ private static void OnLogExecuting(ISqlSugarClient sqlSugar, string operate, str
257261

258262
if (configs.SqlLog.ToDb.Enabled || configs.SqlLog.ToFile.Enabled || configs.SqlLog.ToConsole.Enabled)
259263
{
260-
var httpUser = AutofacHelper.GetScopeService<IHttpUser>();
264+
var httpUser = AutofacHelper.GetService<IHttpUser>();
261265
using (LoggerPropertyConfiguration.Create.AddAopSqlProperty(sqlSugar, configs.SqlLog))
262266
{
263267
Log.Information(
@@ -328,7 +332,7 @@ private static void ConfiguringSoftDeletedFilter(this SqlSugarScopeProvider db)
328332
/// </summary>
329333
private static void ConfiguringTenantFilter(this SqlSugarScopeProvider db)
330334
{
331-
var httpUser = AutofacHelper.GetScopeService<IHttpUser>();
335+
var httpUser = AutofacHelper.GetService<IHttpUser>();
332336

333337
if (httpUser.IsNotNull() && httpUser.TenantId > 0)
334338
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Ape.Volo.Common.DI;
4+
using Ape.Volo.Common.Extensions;
5+
using Microsoft.Extensions.Caching.Distributed;
6+
using Newtonsoft.Json;
7+
using SqlSugar;
8+
9+
namespace Ape.Volo.Common.Caches.SqlSugar;
10+
11+
/// <summary>
12+
/// Distributed缓存
13+
/// 实现SqlSugar.ICacheService
14+
/// </summary>
15+
public class SqlSugarDistributedCache : ICacheService
16+
{
17+
private readonly Lazy<IDistributedCache> _caching = new(AutofacHelper.GetService<IDistributedCache>);
18+
private IDistributedCache Caching => _caching.Value;
19+
20+
21+
public void Add<V>(string key, V value)
22+
{
23+
var valStr = value.ToJson();
24+
Caching.SetString(key, valStr);
25+
}
26+
27+
public void Add<V>(string key, V value, int cacheDurationInSeconds)
28+
{
29+
var valStr = value.ToJson();
30+
DistributedCacheEntryOptions op = new()
31+
{
32+
AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(cacheDurationInSeconds),
33+
};
34+
Caching.SetString(key, valStr, op);
35+
}
36+
37+
public bool ContainsKey<V>(string key)
38+
{
39+
return Caching.Get(key) != null;
40+
}
41+
42+
public V Get<V>(string key)
43+
{
44+
var val = Caching.GetString(key);
45+
if (val == null) return default(V);
46+
return JsonConvert.DeserializeObject<V>(val);
47+
}
48+
49+
public IEnumerable<string> GetAllKey<V>()
50+
{
51+
//throw new NotImplementedException("IDistributedCache不支持模糊查询KEY");
52+
//实现思路 创建一个缓存区。然后添加缓存时,把key增加到这个缓存区
53+
//每次获取时都需要检查一下缓存是否存在 不存在则删除
54+
//这个获取所有key 获取这个定义得缓存区就行了
55+
return new[] { "" };
56+
}
57+
58+
public V GetOrCreate<V>(string cacheKey, Func<V> create, int cacheDurationInSeconds = int.MaxValue)
59+
{
60+
if (ContainsKey<V>(cacheKey))
61+
{
62+
return Get<V>(cacheKey);
63+
}
64+
65+
V val = create();
66+
Add(cacheKey, val, cacheDurationInSeconds);
67+
return val;
68+
}
69+
70+
public void Remove<V>(string key)
71+
{
72+
Caching.Remove(key);
73+
}
74+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Threading;
4+
using Ape.Volo.Common.ConfigOptions;
5+
using Ape.Volo.Common.Extensions;
6+
using Ape.Volo.Common.Global;
7+
using Microsoft.Extensions.Options;
8+
using Newtonsoft.Json;
9+
using SqlSugar;
10+
using StackExchange.Redis;
11+
12+
namespace Ape.Volo.Common.Caches.SqlSugar;
13+
14+
/// <summary>
15+
/// redis缓存
16+
/// 实现SqlSugar.ICacheService
17+
/// </summary>
18+
public class SqlSugarRedisCache : ICacheService
19+
{
20+
private static IDatabase _database;
21+
22+
public SqlSugarRedisCache()
23+
{
24+
ThreadPool.SetMinThreads(200, 200);
25+
var options = new ConfigurationOptions
26+
{
27+
AbortOnConnectFail = AppSettings.GetValue<bool>("Redis", "AbortOnConnectFail"),
28+
AllowAdmin = AppSettings.GetValue<bool>("Redis", "AllowAdmin"),
29+
ConnectRetry = AppSettings.GetValue<int>("Redis", "ConnectRetry"),
30+
ConnectTimeout = AppSettings.GetValue<int>("Redis", "ConnectTimeout"),
31+
KeepAlive = AppSettings.GetValue<int>("Redis", "KeepAlive"),
32+
SyncTimeout = AppSettings.GetValue<int>("Redis", "SyncTimeout"),
33+
EndPoints =
34+
{
35+
AppSettings.GetValue<string>("Redis", "Host") + ":" + AppSettings.GetValue<int>("Redis", "Port")
36+
},
37+
ServiceName = AppSettings.GetValue<string>("Redis", "Name") + "_SqlSugarCache",
38+
};
39+
if (!string.IsNullOrWhiteSpace(AppSettings.GetValue<string>("Redis", "Password")))
40+
{
41+
options.Password = AppSettings.GetValue<string>("Redis", "Password");
42+
}
43+
44+
var connection = ConnectionMultiplexer.Connect(options);
45+
_database = connection.GetDatabase(AppSettings.GetValue<int>("Redis", "Index") + 1);
46+
}
47+
48+
public void Add<V>(string key, V value)
49+
{
50+
var valStr = value.ToJson();
51+
_database.StringSet(key, valStr);
52+
}
53+
54+
public void Add<V>(string key, V value, int cacheDurationInSeconds)
55+
{
56+
var valStr = value.ToJson();
57+
var expireTime = new TimeSpan(0, 0, 0, cacheDurationInSeconds);
58+
_database.StringSet(key, valStr, expireTime);
59+
}
60+
61+
public bool ContainsKey<V>(string key)
62+
{
63+
return _database.KeyExists(key);
64+
}
65+
66+
public V Get<V>(string key)
67+
{
68+
var val = _database.StringGet(key);
69+
var redisValue = _database.StringGet(key);
70+
if (!redisValue.HasValue)
71+
return default;
72+
return JsonConvert.DeserializeObject<V>(val);
73+
}
74+
75+
public IEnumerable<string> GetAllKey<V>()
76+
{
77+
var pattern = "SqlSugarDataCache.*";
78+
var redisResult = _database.ScriptEvaluate(LuaScript.Prepare(
79+
" local res = redis.call('KEYS', @keypattern) " +
80+
" return res "), new { keypattern = pattern });
81+
string[] preSult = (string[])redisResult;
82+
return preSult;
83+
}
84+
85+
public V GetOrCreate<V>(string cacheKey, Func<V> create, int cacheDurationInSeconds = int.MaxValue)
86+
{
87+
if (ContainsKey<V>(cacheKey))
88+
{
89+
return Get<V>(cacheKey);
90+
}
91+
92+
V val = create();
93+
Add(cacheKey, val, cacheDurationInSeconds);
94+
return val;
95+
}
96+
97+
public void Remove<V>(string key)
98+
{
99+
_database.KeyDelete(key);
100+
}
101+
}

Ape.Volo.Common/DI/AutofacHelper.cs

+31-13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
using Autofac;
1+
using System;
2+
using Ape.Volo.Common.Helper.Serilog;
3+
using Autofac;
4+
using Autofac.Core.Registration;
25
using Microsoft.AspNetCore.Http;
6+
using Serilog;
37

48
namespace Ape.Volo.Common.DI;
59

@@ -8,28 +12,42 @@ namespace Ape.Volo.Common.DI;
812
/// </summary>
913
public static class AutofacHelper
1014
{
15+
private static readonly ILogger Logger = SerilogManager.GetLogger(typeof(AutofacHelper));
16+
1117
public static ILifetimeScope Container { get; set; }
1218
// private static readonly Lazy<ILifetimeScope> LazyContainer = new(() => new ContainerBuilder().Build());
1319
//
1420
// public static ILifetimeScope Container => LazyContainer.Value;
1521

1622
/// <summary>
17-
/// 获取全局服务
23+
/// 优先从当前 HTTP 请求范围内获取服务,如果不可用则从全局容器获取服务
1824
/// </summary>
1925
/// <typeparam name="T">接口类型</typeparam>
20-
/// <returns></returns>
26+
/// <returns>返回服务实例,如果服务未注册则返回 null</returns>
2127
public static T GetService<T>() where T : class
2228
{
23-
return Container.Resolve<T>();
24-
}
29+
var httpContextAccessor = Container.Resolve<IHttpContextAccessor>();
2530

26-
/// <summary>
27-
/// 获取当前请求为生命周期的服务
28-
/// </summary>
29-
/// <typeparam name="T">接口类型</typeparam>
30-
/// <returns></returns>
31-
public static T GetScopeService<T>() where T : class
32-
{
33-
return (T)GetService<IHttpContextAccessor>().HttpContext?.RequestServices.GetService(typeof(T));
31+
var requestServices = httpContextAccessor?.HttpContext?.RequestServices;
32+
var service = requestServices?.GetService(typeof(T));
33+
if (service is T typedService)
34+
{
35+
return typedService;
36+
}
37+
38+
try
39+
{
40+
return Container.Resolve<T>();
41+
}
42+
catch (ComponentNotRegisteredException)
43+
{
44+
Logger.Fatal($" 类型服务{typeof(T)} 未注册。");
45+
return null;
46+
}
47+
catch (System.Exception ex)
48+
{
49+
Logger.Fatal($"无法解析类型为 {typeof(T)} 的服务。{ex.Message}");
50+
throw new InvalidOperationException($"无法解析类型为 {typeof(T)} 的服务。", ex);
51+
}
3452
}
3553
}

Ape.Volo.Common/Extensions/Ext.HttpContext.cs

-25
This file was deleted.

Ape.Volo.Common/Extensions/Ext.Uri.cs

-25
This file was deleted.

0 commit comments

Comments
 (0)