docs: add xml comments and update ignore rules
This commit is contained in:
@@ -12,11 +12,21 @@ namespace TakeoutSaaS.Infrastructure.Dictionary.Persistence;
|
||||
internal sealed class DictionaryDesignTimeDbContextFactory
|
||||
: DesignTimeDbContextFactoryBase<DictionaryDbContext>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化字典库设计时上下文工厂。
|
||||
/// </summary>
|
||||
public DictionaryDesignTimeDbContextFactory()
|
||||
: base(DatabaseConstants.DictionaryDataSource, "TAKEOUTSAAS_DICTIONARY_CONNECTION")
|
||||
{
|
||||
}
|
||||
|
||||
// 创建设计时上下文
|
||||
/// <summary>
|
||||
/// 创建设计时的 DictionaryDbContext。
|
||||
/// </summary>
|
||||
/// <param name="options">上下文配置。</param>
|
||||
/// <param name="tenantProvider">租户提供器。</param>
|
||||
/// <param name="currentUserAccessor">当前用户访问器。</param>
|
||||
/// <returns>DictionaryDbContext 实例。</returns>
|
||||
protected override DictionaryDbContext CreateContext(
|
||||
DbContextOptions<DictionaryDbContext> options,
|
||||
ITenantProvider tenantProvider,
|
||||
|
||||
@@ -11,42 +11,92 @@ namespace TakeoutSaaS.Infrastructure.Dictionary.Repositories;
|
||||
/// </summary>
|
||||
public sealed class EfDictionaryRepository(DictionaryDbContext context) : IDictionaryRepository
|
||||
{
|
||||
/// <summary>
|
||||
/// 根据分组 ID 查询分组。
|
||||
/// </summary>
|
||||
/// <param name="id">分组 ID。</param>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>匹配分组或 null。</returns>
|
||||
public Task<DictionaryGroup?> FindGroupByIdAsync(long id, CancellationToken cancellationToken = default)
|
||||
=> context.DictionaryGroups.FirstOrDefaultAsync(group => group.Id == id, cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// 根据分组编码查询分组。
|
||||
/// </summary>
|
||||
/// <param name="code">分组编码。</param>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>匹配分组或 null。</returns>
|
||||
public Task<DictionaryGroup?> FindGroupByCodeAsync(string code, CancellationToken cancellationToken = default)
|
||||
=> context.DictionaryGroups.FirstOrDefaultAsync(group => group.Code == code, cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// 搜索分组列表。
|
||||
/// </summary>
|
||||
/// <param name="scope">字典作用域。</param>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>分组列表。</returns>
|
||||
public async Task<IReadOnlyList<DictionaryGroup>> SearchGroupsAsync(DictionaryScope? scope, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 1. 构建分组查询
|
||||
var query = context.DictionaryGroups.AsNoTracking();
|
||||
if (scope.HasValue)
|
||||
{
|
||||
// 2. 按作用域过滤
|
||||
query = query.Where(group => group.Scope == scope.Value);
|
||||
}
|
||||
|
||||
// 3. 排序返回
|
||||
return await query
|
||||
.OrderBy(group => group.Code)
|
||||
.ToListAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新增分组。
|
||||
/// </summary>
|
||||
/// <param name="group">分组实体。</param>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>异步任务。</returns>
|
||||
public Task AddGroupAsync(DictionaryGroup group, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 1. 添加分组
|
||||
context.DictionaryGroups.Add(group);
|
||||
// 2. 返回完成任务
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除分组。
|
||||
/// </summary>
|
||||
/// <param name="group">分组实体。</param>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>异步任务。</returns>
|
||||
public Task RemoveGroupAsync(DictionaryGroup group, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 1. 移除分组
|
||||
context.DictionaryGroups.Remove(group);
|
||||
// 2. 返回完成任务
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据条目 ID 查询字典项。
|
||||
/// </summary>
|
||||
/// <param name="id">条目 ID。</param>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>匹配条目或 null。</returns>
|
||||
public Task<DictionaryItem?> FindItemByIdAsync(long id, CancellationToken cancellationToken = default)
|
||||
=> context.DictionaryItems.FirstOrDefaultAsync(item => item.Id == id, cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定分组下的条目列表。
|
||||
/// </summary>
|
||||
/// <param name="groupId">分组 ID。</param>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>条目列表。</returns>
|
||||
public async Task<IReadOnlyList<DictionaryItem>> GetItemsByGroupIdAsync(long groupId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 1. 过滤分组
|
||||
return await context.DictionaryItems
|
||||
.AsNoTracking()
|
||||
.Where(item => item.GroupId == groupId)
|
||||
@@ -54,23 +104,53 @@ public sealed class EfDictionaryRepository(DictionaryDbContext context) : IDicti
|
||||
.ToListAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新增字典项。
|
||||
/// </summary>
|
||||
/// <param name="item">字典项。</param>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>异步任务。</returns>
|
||||
public Task AddItemAsync(DictionaryItem item, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 1. 添加条目
|
||||
context.DictionaryItems.Add(item);
|
||||
// 2. 返回完成任务
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除字典项。
|
||||
/// </summary>
|
||||
/// <param name="item">字典项。</param>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>异步任务。</returns>
|
||||
public Task RemoveItemAsync(DictionaryItem item, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 1. 移除条目
|
||||
context.DictionaryItems.Remove(item);
|
||||
// 2. 返回完成任务
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 持久化变更。
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>保存任务。</returns>
|
||||
public Task SaveChangesAsync(CancellationToken cancellationToken = default)
|
||||
=> context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// 根据编码集合获取条目列表,可包含系统级条目。
|
||||
/// </summary>
|
||||
/// <param name="codes">分组编码集合。</param>
|
||||
/// <param name="tenantId">租户 ID。</param>
|
||||
/// <param name="includeSystem">是否包含系统级。</param>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>条目列表。</returns>
|
||||
public async Task<IReadOnlyList<DictionaryItem>> GetItemsByCodesAsync(IEnumerable<string> codes, long tenantId, bool includeSystem, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 1. 规范化编码
|
||||
var normalizedCodes = codes
|
||||
.Where(code => !string.IsNullOrWhiteSpace(code))
|
||||
.Select(code => code.Trim().ToLowerInvariant())
|
||||
@@ -82,14 +162,17 @@ public sealed class EfDictionaryRepository(DictionaryDbContext context) : IDicti
|
||||
return Array.Empty<DictionaryItem>();
|
||||
}
|
||||
|
||||
// 2. 构建查询并忽略 QueryFilter
|
||||
var query = context.DictionaryItems
|
||||
.AsNoTracking()
|
||||
.IgnoreQueryFilters()
|
||||
.Include(item => item.Group)
|
||||
.Where(item => normalizedCodes.Contains(item.Group!.Code));
|
||||
|
||||
// 3. 按租户或系统级过滤
|
||||
query = query.Where(item => item.TenantId == tenantId || (includeSystem && item.TenantId == 0));
|
||||
|
||||
// 4. 排序返回
|
||||
return await query
|
||||
.OrderBy(item => item.SortOrder)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
@@ -15,8 +15,16 @@ public sealed class DistributedDictionaryCache(IDistributedCache cache, IOptions
|
||||
private readonly DictionaryCacheOptions _options = options.Value;
|
||||
private readonly JsonSerializerOptions _serializerOptions = new(JsonSerializerDefaults.Web);
|
||||
|
||||
/// <summary>
|
||||
/// 读取指定租户与编码的字典缓存。
|
||||
/// </summary>
|
||||
/// <param name="tenantId">租户 ID。</param>
|
||||
/// <param name="code">字典编码。</param>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>字典项集合或 null。</returns>
|
||||
public async Task<IReadOnlyList<DictionaryItemDto>?> GetAsync(long tenantId, string code, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 1. 拼装缓存键
|
||||
var cacheKey = BuildKey(tenantId, code);
|
||||
var payload = await cache.GetAsync(cacheKey, cancellationToken);
|
||||
if (payload == null || payload.Length == 0)
|
||||
@@ -24,11 +32,21 @@ public sealed class DistributedDictionaryCache(IDistributedCache cache, IOptions
|
||||
return null;
|
||||
}
|
||||
|
||||
// 2. 反序列化
|
||||
return JsonSerializer.Deserialize<List<DictionaryItemDto>>(payload, _serializerOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置指定租户与编码的字典缓存。
|
||||
/// </summary>
|
||||
/// <param name="tenantId">租户 ID。</param>
|
||||
/// <param name="code">字典编码。</param>
|
||||
/// <param name="items">字典项集合。</param>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>异步任务。</returns>
|
||||
public Task SetAsync(long tenantId, string code, IReadOnlyList<DictionaryItemDto> items, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 1. 序列化并写入缓存
|
||||
var cacheKey = BuildKey(tenantId, code);
|
||||
var payload = JsonSerializer.SerializeToUtf8Bytes(items, _serializerOptions);
|
||||
var options = new DistributedCacheEntryOptions
|
||||
@@ -38,8 +56,16 @@ public sealed class DistributedDictionaryCache(IDistributedCache cache, IOptions
|
||||
return cache.SetAsync(cacheKey, payload, options, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除指定租户与编码的缓存。
|
||||
/// </summary>
|
||||
/// <param name="tenantId">租户 ID。</param>
|
||||
/// <param name="code">字典编码。</param>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>异步任务。</returns>
|
||||
public Task RemoveAsync(long tenantId, string code, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// 1. 删除缓存键
|
||||
var cacheKey = BuildKey(tenantId, code);
|
||||
return cache.RemoveAsync(cacheKey, cancellationToken);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user