From 4521212a90d69dfdf2fdbe2eacd9e870364ade1c Mon Sep 17 00:00:00 2001 From: chenchun Date: Thu, 6 Nov 2025 11:29:21 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E7=BC=93=E5=AD=98=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 Yi.Framework.Rbac.Application.Services.FileService 中注入 IMemoryCache,用于缓存文件元数据,减少对仓储的重复读取。 - 在 Get 方法中通过 key "File:{code}" 缓存 FileCacheItem,设置绝对过期时间为 1 天。 - 缓存项使用 Mapster 适配为 FileCacheItem,再适配回 FileAggregateRoot(保留现有逻辑判断和路径获取)。 - 新增缓存模型 Yi.Framework.Rbac.Domain.Shared.Caches.FileCacheItem(包含 Id、FileSize、FileName、FilePath、创建/修改信息等)。 - 增加并调整相关 using 引用(Microsoft.Extensions.Caching.Memory、Volo.Abp.Caching、Domain.Shared.Caches)。 - 同时修复了保存多文件时的缩进/空格格式(不影响功能)。 --- .../Services/FileService.cs | 27 ++++++++++++----- .../Caches/FileCacheItem.cs | 29 +++++++++++++++++++ 2 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain.Shared/Caches/FileCacheItem.cs diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/FileService.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/FileService.cs index 90d6b5ef..7a67e6ae 100644 --- a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/FileService.cs +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Application/Services/FileService.cs @@ -6,8 +6,10 @@ using System.Threading.Tasks; using Mapster; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Caching.Memory; using Volo.Abp; using Volo.Abp.Application.Services; +using Volo.Abp.Caching; using Volo.Abp.Domain.Repositories; using Volo.Abp.Guids; using Yi.Framework.Core.Enums; @@ -16,6 +18,7 @@ using Yi.Framework.Rbac.Application.Contracts.Dtos.FileManager; using Yi.Framework.Rbac.Application.Contracts.IServices; using Yi.Framework.Rbac.Domain.Entities; using Yi.Framework.Rbac.Domain.Managers; +using Yi.Framework.Rbac.Domain.Shared.Caches; namespace Yi.Framework.Rbac.Application.Services { @@ -23,11 +26,13 @@ namespace Yi.Framework.Rbac.Application.Services { private readonly IRepository _repository; private readonly FileManager _fileManager; + private readonly IMemoryCache _memoryCache; - public FileService(IRepository repository, FileManager fileManager) + public FileService(IRepository repository, FileManager fileManager, IMemoryCache memoryCache) { _repository = repository; _fileManager = fileManager; + _memoryCache = memoryCache; } /// @@ -37,7 +42,14 @@ namespace Yi.Framework.Rbac.Application.Services [Route("file/{code}/{isThumbnail?}")] public async Task Get([FromRoute] Guid code, [FromRoute] bool? isThumbnail) { - var file = await _repository.GetAsync(x => x.Id == code); + var fileCache = await _memoryCache.GetOrCreateAsync($"File:{code}", async (options) => + { + options.AbsoluteExpiration = DateTime.Now.AddDays(1); + var file = await _repository.GetAsync(x => x.Id == code); + if (file == null!) return null; + return file.Adapt(); + }); + var file = fileCache?.Adapt(); var path = file?.GetQueryFileSavePath(isThumbnail); if (path is null || !File.Exists(path)) { @@ -58,12 +70,13 @@ namespace Yi.Framework.Rbac.Application.Services for (int i = 0; i < file.Count; i++) { - var entity= entities[i]; - using (var steam = file[i].OpenReadStream()) - { - await _fileManager.SaveFileAsync(entity,steam); - } + var entity = entities[i]; + using (var steam = file[i].OpenReadStream()) + { + await _fileManager.SaveFileAsync(entity, steam); + } } + return entities.Adapt>(); } } diff --git a/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain.Shared/Caches/FileCacheItem.cs b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain.Shared/Caches/FileCacheItem.cs new file mode 100644 index 00000000..a8bfe3ab --- /dev/null +++ b/Yi.Abp.Net8/module/rbac/Yi.Framework.Rbac.Domain.Shared/Caches/FileCacheItem.cs @@ -0,0 +1,29 @@ +namespace Yi.Framework.Rbac.Domain.Shared.Caches; + +public class FileCacheItem +{ + public Guid Id { get; set; } + + /// + /// 文件大小 + /// + public decimal FileSize { get; set; } + + /// + /// 文件名 + /// + public string FileName { get; set; } + + /// + /// 文件路径 + /// + public string FilePath { get; set; } + + public DateTime CreationTime { get; set; } + + public Guid? CreatorId { get; set; } + + public Guid? LastModifierId { get; set; } + + public DateTime? LastModificationTime { get; set; } +} \ No newline at end of file From 2ec7b5f4fd396a0510f539f3c6a3d53a6f92495e Mon Sep 17 00:00:00 2001 From: chenchun Date: Thu, 13 Nov 2025 16:49:44 +0800 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=BD=AF=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E6=97=B6=E7=A9=BA=E5=BC=95=E7=94=A8=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在 SqlSugarRepository.cs 中对 ISoftDelete 分支增加 GetByIdAsync 返回 null 的判断,避免在实体为 null 时继续反射赋值导致 NullReferenceException。若实体不存在,直接返回 false。 --- .../Yi.Framework.SqlSugarCore/Repositories/SqlSugarRepository.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Yi.Abp.Net8/framework/Yi.Framework.SqlSugarCore/Repositories/SqlSugarRepository.cs b/Yi.Abp.Net8/framework/Yi.Framework.SqlSugarCore/Repositories/SqlSugarRepository.cs index 7468ee9b..9243e5ed 100644 --- a/Yi.Abp.Net8/framework/Yi.Framework.SqlSugarCore/Repositories/SqlSugarRepository.cs +++ b/Yi.Abp.Net8/framework/Yi.Framework.SqlSugarCore/Repositories/SqlSugarRepository.cs @@ -264,6 +264,7 @@ namespace Yi.Framework.SqlSugarCore.Repositories if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity))) { var entity = await GetByIdAsync(id); + if (entity == null) return false; //反射赋值 ReflexHelper.SetModelValue(nameof(ISoftDelete.IsDeleted), true, entity); return await UpdateAsync(entity);