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); }