using Microsoft.EntityFrameworkCore;
using TakeoutSaaS.Domain.Identity.Entities;
using TakeoutSaaS.Domain.Identity.Repositories;
namespace TakeoutSaaS.Infrastructure.Identity.Persistence;
///
/// EF 角色-权限仓储。
///
public sealed class EfRolePermissionRepository(IdentityDbContext dbContext) : IRolePermissionRepository
{
public Task> GetByRoleIdsAsync(long tenantId, IEnumerable roleIds, CancellationToken cancellationToken = default)
=> dbContext.RolePermissions.AsNoTracking()
.Where(x => x.TenantId == tenantId && roleIds.Contains(x.RoleId))
.ToListAsync(cancellationToken)
.ContinueWith(t => (IReadOnlyList)t.Result, cancellationToken);
public async Task AddRangeAsync(IEnumerable rolePermissions, CancellationToken cancellationToken = default)
{
var toAdd = rolePermissions as RolePermission[] ?? rolePermissions.ToArray();
if (toAdd.Length == 0)
{
return;
}
await dbContext.RolePermissions.AddRangeAsync(toAdd, cancellationToken);
}
public async Task ReplaceRolePermissionsAsync(long tenantId, long roleId, IEnumerable permissionIds, CancellationToken cancellationToken = default)
{
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);
});
}
public Task SaveChangesAsync(CancellationToken cancellationToken = default)
=> dbContext.SaveChangesAsync(cancellationToken);
}