From 6b50d7fc50a644acb4a1a8fda1a0328a59f86cec Mon Sep 17 00:00:00 2001 From: OpenClaw Agent Date: Tue, 17 Mar 2026 09:26:26 +0000 Subject: [PATCH] =?UTF-8?q?refactor:=20SqlSugarScope=E6=B3=A8=E5=86=8C?= =?UTF-8?q?=E4=B8=BASingleton=E5=AE=9E=E7=8E=B0=E7=BA=BF=E7=A8=8B=E5=AE=89?= =?UTF-8?q?=E5=85=A8=EF=BC=8C=E7=A7=BB=E9=99=A4=E6=89=8B=E5=8A=A8=E4=BF=A1?= =?UTF-8?q?=E5=8F=B7=E9=87=8F=E9=99=90=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AssetManager.Data/DatabaseExtensions.cs | 4 +- .../Services/MarketDataService.cs | 69 +++++-------------- 2 files changed, 19 insertions(+), 54 deletions(-) diff --git a/AssetManager.Data/DatabaseExtensions.cs b/AssetManager.Data/DatabaseExtensions.cs index 27e969d..76efdb2 100755 --- a/AssetManager.Data/DatabaseExtensions.cs +++ b/AssetManager.Data/DatabaseExtensions.cs @@ -8,7 +8,9 @@ public static class DatabaseExtensions { public static IServiceCollection AddDatabase(this IServiceCollection services) { - services.AddScoped(s => + // 使用 Singleton 注册 SqlSugarScope(线程安全,内部使用 AsyncLocal) + // SqlSugarScope 设计上支持并发,会自动管理连接池 + services.AddSingleton(s => { return SqlSugarConfig.GetSqlSugarClient(); }); diff --git a/AssetManager.Infrastructure/Services/MarketDataService.cs b/AssetManager.Infrastructure/Services/MarketDataService.cs index a3427f4..d5e5206 100755 --- a/AssetManager.Infrastructure/Services/MarketDataService.cs +++ b/AssetManager.Infrastructure/Services/MarketDataService.cs @@ -20,9 +20,6 @@ public class MarketDataService : IMarketDataService private readonly ITiingoMarketService _tiingoService; private readonly IOkxMarketService _okxService; private readonly IMarketDataRepository _marketDataRepo; - - // 限制数据库并发访问,避免 SqlSugar 连接状态冲突 - private static readonly SemaphoreSlim _dbSemaphore = new(3, 3); public MarketDataService( ILogger logger, @@ -47,29 +44,20 @@ public class MarketDataService : IMarketDataService { _logger.LogInformation("获取实时价格: {Symbol}, 资产类型: {AssetType}", symbol, assetType); - // 限制数据库并发访问 - await _dbSemaphore.WaitAsync(); - try - { - // 先查缓存 - var cached = await _marketDataRepo.GetPriceCacheAsync(symbol, assetType); + // 先查缓存 + var cached = await _marketDataRepo.GetPriceCacheAsync(symbol, assetType); - if (cached != null) - { - _logger.LogDebug("缓存命中: {Symbol} {AssetType}, 价格: {Price}", symbol, assetType, cached.Price); - return new MarketPriceResponse - { - Symbol = cached.Symbol, - Price = cached.Price, - PreviousClose = cached.PreviousClose ?? 0, - Timestamp = cached.FetchedAt, - AssetType = cached.AssetType - }; - } - } - finally + if (cached != null) { - _dbSemaphore.Release(); + _logger.LogDebug("缓存命中: {Symbol} {AssetType}, 价格: {Price}", symbol, assetType, cached.Price); + return new MarketPriceResponse + { + Symbol = cached.Symbol, + Price = cached.Price, + PreviousClose = cached.PreviousClose ?? 0, + Timestamp = cached.FetchedAt, + AssetType = cached.AssetType + }; } // 缓存未命中,调用API @@ -120,17 +108,8 @@ public class MarketDataService : IMarketDataService _logger.LogInformation("获取历史数据: {Symbol}, 资产类型: {AssetType}, 周期: {Timeframe}, 数量: {Limit}", symbol, assetType, timeframe, limit); - // 限制数据库并发访问 - await _dbSemaphore.WaitAsync(); - List cachedKlines; - try - { - cachedKlines = await _marketDataRepo.GetKlineCacheAsync(symbol, assetType, timeframe, limit); - } - finally - { - _dbSemaphore.Release(); - } + // 先查缓存 + var cachedKlines = await _marketDataRepo.GetKlineCacheAsync(symbol, assetType, timeframe, limit); // 缓存足够,直接返回 if (cachedKlines.Count >= limit) @@ -235,15 +214,7 @@ public class MarketDataService : IMarketDataService ExpiredAt = GetCacheExpirationTime(assetType) }; - await _dbSemaphore.WaitAsync(); - try - { - await _marketDataRepo.SavePriceCacheAsync(cacheEntity); - } - finally - { - _dbSemaphore.Release(); - } + await _marketDataRepo.SavePriceCacheAsync(cacheEntity); _logger.LogDebug("缓存写入: {Symbol} {AssetType}, 过期时间: {ExpiredAt}", symbol, assetType, cacheEntity.ExpiredAt); } @@ -264,15 +235,7 @@ public class MarketDataService : IMarketDataService FetchedAt = DateTime.Now }).ToList(); - await _dbSemaphore.WaitAsync(); - try - { - await _marketDataRepo.SaveKlineCacheBatchAsync(cacheEntities); - } - finally - { - _dbSemaphore.Release(); - } + await _marketDataRepo.SaveKlineCacheBatchAsync(cacheEntities); _logger.LogDebug("历史K线缓存写入: {Symbol} {AssetType} {Timeframe}, 数量: {Count}", symbol, assetType, timeframe, cacheEntities.Count); }