93 lines
3.9 KiB
C#
93 lines
3.9 KiB
C#
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);
|
||
}
|