Files
TakeoutSaaS.TenantApi/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfRolePermissionRepository.cs
2026-01-30 01:04:51 +00:00

93 lines
3.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Microsoft.EntityFrameworkCore;
using TakeoutSaaS.Domain.Identity.Entities;
using TakeoutSaaS.Domain.Identity.Repositories;
namespace TakeoutSaaS.Infrastructure.Identity.Persistence;
/// <summary>
/// EF 角色-权限仓储。
/// </summary>
public sealed class EfRolePermissionRepository(IdentityDbContext dbContext) : IRolePermissionRepository
{
/// <summary>
/// 根据角色 ID 集合获取角色权限映射。
/// </summary>
/// <param name="tenantId">租户 ID。</param>
/// <param name="roleIds">角色 ID 集合。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>角色权限映射列表。</returns>
public async Task<IReadOnlyList<RolePermission>> GetByRoleIdsAsync(long tenantId, IEnumerable<long> roleIds, CancellationToken cancellationToken = default)
{
// 1. 查询角色权限映射
var mappings = await dbContext.RolePermissions
.AsNoTracking()
.Where(x => x.TenantId == tenantId && x.DeletedAt == null && roleIds.Contains(x.RoleId))
.ToListAsync(cancellationToken);
// 2. (空行后) 返回只读列表
return mappings;
}
/// <summary>
/// 批量新增角色权限。
/// </summary>
/// <param name="rolePermissions">角色权限集合。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
public async Task AddRangeAsync(IEnumerable<RolePermission> rolePermissions, CancellationToken cancellationToken = default)
{
// 1. 转为数组便于计数
var toAdd = rolePermissions as RolePermission[] ?? rolePermissions.ToArray();
if (toAdd.Length == 0)
{
return;
}
// 2. 批量插入
await dbContext.RolePermissions.AddRangeAsync(toAdd, cancellationToken);
}
/// <summary>
/// 替换指定角色的权限集合。
/// </summary>
/// <param name="tenantId">租户 ID。</param>
/// <param name="roleId">角色 ID。</param>
/// <param name="permissionIds">权限 ID 集合。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
public async Task ReplaceRolePermissionsAsync(long tenantId, long roleId, IEnumerable<long> permissionIds, CancellationToken cancellationToken = default)
{
// 1. 使用执行策略保证可靠性
var strategy = dbContext.Database.CreateExecutionStrategy();
await strategy.ExecuteAsync(async () =>
{
await using var trx = await dbContext.Database.BeginTransactionAsync(cancellationToken);
// 1. 删除旧记录(原生 SQL避免跟踪干扰
await dbContext.Database.ExecuteSqlRawAsync(
"DELETE FROM \"role_permissions\" WHERE \"TenantId\" = {0} AND \"RoleId\" = {1};",
parameters: new object[] { tenantId, roleId },
cancellationToken: cancellationToken);
// 2. 插入新记录(防重复)
foreach (var permissionId in permissionIds.Distinct())
{
await dbContext.Database.ExecuteSqlRawAsync(
"INSERT INTO \"role_permissions\" (\"TenantId\",\"RoleId\",\"PermissionId\",\"CreatedAt\",\"CreatedBy\",\"UpdatedAt\",\"UpdatedBy\",\"DeletedAt\",\"DeletedBy\") VALUES ({0},{1},{2},NOW(),NULL,NULL,NULL,NULL,NULL) ON CONFLICT DO NOTHING;",
parameters: new object[] { tenantId, roleId, permissionId },
cancellationToken: cancellationToken);
}
await trx.CommitAsync(cancellationToken);
});
}
/// <summary>
/// 保存仓储变更。
/// </summary>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>保存任务。</returns>
public Task SaveChangesAsync(CancellationToken cancellationToken = default)
=> dbContext.SaveChangesAsync(cancellationToken);
}