diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfRolePermissionRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfRolePermissionRepository.cs index f5ad1e1..c1f0d4b 100644 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfRolePermissionRepository.cs +++ b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfRolePermissionRepository.cs @@ -28,25 +28,30 @@ public sealed class EfRolePermissionRepository(IdentityDbContext dbContext) : IR public async Task ReplaceRolePermissionsAsync(long tenantId, long roleId, IEnumerable permissionIds, CancellationToken cancellationToken = default) { - await using var trx = await dbContext.Database.BeginTransactionAsync(cancellationToken); - - var existing = await dbContext.RolePermissions - .Where(x => x.TenantId == tenantId && x.RoleId == roleId) - .ToListAsync(cancellationToken); - - dbContext.RolePermissions.RemoveRange(existing); - await dbContext.SaveChangesAsync(cancellationToken); - - var toAdd = permissionIds.Distinct().Select(permissionId => new RolePermission + var strategy = dbContext.Database.CreateExecutionStrategy(); + await strategy.ExecuteAsync(async () => { - TenantId = tenantId, - RoleId = roleId, - PermissionId = permissionId - }); + await using var trx = await dbContext.Database.BeginTransactionAsync(cancellationToken); - await dbContext.RolePermissions.AddRangeAsync(toAdd, cancellationToken); - await dbContext.SaveChangesAsync(cancellationToken); - await trx.CommitAsync(cancellationToken); + var existing = await dbContext.RolePermissions + .Where(x => x.TenantId == tenantId && x.RoleId == roleId) + .ToListAsync(cancellationToken); + + dbContext.RolePermissions.RemoveRange(existing); + await dbContext.SaveChangesAsync(cancellationToken); + + var toAdd = permissionIds.Distinct().Select(permissionId => new RolePermission + { + TenantId = tenantId, + RoleId = roleId, + PermissionId = permissionId + }); + + await dbContext.RolePermissions.AddRangeAsync(toAdd, cancellationToken); + await dbContext.SaveChangesAsync(cancellationToken); + + await trx.CommitAsync(cancellationToken); + }); } public Task SaveChangesAsync(CancellationToken cancellationToken = default) diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfRoleTemplateRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfRoleTemplateRepository.cs index d505e3b..309acec 100644 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfRoleTemplateRepository.cs +++ b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfRoleTemplateRepository.cs @@ -86,35 +86,42 @@ public sealed class EfRoleTemplateRepository(IdentityDbContext dbContext) : IRol private async Task ReplacePermissionsInternalAsync(RoleTemplate template, IEnumerable permissionCodes, CancellationToken cancellationToken) { - await using var trx = await dbContext.Database.BeginTransactionAsync(cancellationToken); - - // 确保模板已持久化,便于 FK 正确填充 - if (!dbContext.Entry(template).IsKeySet || template.Id == 0) + var strategy = dbContext.Database.CreateExecutionStrategy(); + await strategy.ExecuteAsync(async () => { + await using var trx = await dbContext.Database.BeginTransactionAsync(cancellationToken); + + // 1. 确保模板已持久化,便于 FK 正确填充 + if (!dbContext.Entry(template).IsKeySet || template.Id == 0) + { + await dbContext.SaveChangesAsync(cancellationToken); + } + + // 2. 归一化权限编码 + var normalized = permissionCodes + .Where(code => !string.IsNullOrWhiteSpace(code)) + .Select(code => code.Trim()) + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToArray(); + + // 3. 清空旧权限 + var existing = await dbContext.RoleTemplatePermissions + .Where(x => x.RoleTemplateId == template.Id) + .ToListAsync(cancellationToken); + dbContext.RoleTemplatePermissions.RemoveRange(existing); await dbContext.SaveChangesAsync(cancellationToken); - } - var normalized = permissionCodes - .Where(code => !string.IsNullOrWhiteSpace(code)) - .Select(code => code.Trim()) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToArray(); + // 4. 插入新权限 + var toAdd = normalized.Select(code => new RoleTemplatePermission + { + RoleTemplateId = template.Id, + PermissionCode = code + }); - var existing = await dbContext.RoleTemplatePermissions - .Where(x => x.RoleTemplateId == template.Id) - .ToListAsync(cancellationToken); + await dbContext.RoleTemplatePermissions.AddRangeAsync(toAdd, cancellationToken); + await dbContext.SaveChangesAsync(cancellationToken); - dbContext.RoleTemplatePermissions.RemoveRange(existing); - await dbContext.SaveChangesAsync(cancellationToken); - - var toAdd = normalized.Select(code => new RoleTemplatePermission - { - RoleTemplateId = template.Id, - PermissionCode = code + await trx.CommitAsync(cancellationToken); }); - - await dbContext.RoleTemplatePermissions.AddRangeAsync(toAdd, cancellationToken); - await dbContext.SaveChangesAsync(cancellationToken); - await trx.CommitAsync(cancellationToken); } } diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfUserRoleRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfUserRoleRepository.cs index 6e1f2ae..8b26acb 100644 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfUserRoleRepository.cs +++ b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfUserRoleRepository.cs @@ -23,25 +23,30 @@ public sealed class EfUserRoleRepository(IdentityDbContext dbContext) : IUserRol public async Task ReplaceUserRolesAsync(long tenantId, long userId, IEnumerable roleIds, CancellationToken cancellationToken = default) { - await using var trx = await dbContext.Database.BeginTransactionAsync(cancellationToken); - - var existing = await dbContext.UserRoles - .Where(x => x.TenantId == tenantId && x.UserId == userId) - .ToListAsync(cancellationToken); - - dbContext.UserRoles.RemoveRange(existing); - await dbContext.SaveChangesAsync(cancellationToken); - - var toAdd = roleIds.Distinct().Select(roleId => new UserRole + var strategy = dbContext.Database.CreateExecutionStrategy(); + await strategy.ExecuteAsync(async () => { - TenantId = tenantId, - UserId = userId, - RoleId = roleId - }); + await using var trx = await dbContext.Database.BeginTransactionAsync(cancellationToken); - await dbContext.UserRoles.AddRangeAsync(toAdd, cancellationToken); - await dbContext.SaveChangesAsync(cancellationToken); - await trx.CommitAsync(cancellationToken); + var existing = await dbContext.UserRoles + .Where(x => x.TenantId == tenantId && x.UserId == userId) + .ToListAsync(cancellationToken); + + dbContext.UserRoles.RemoveRange(existing); + await dbContext.SaveChangesAsync(cancellationToken); + + var toAdd = roleIds.Distinct().Select(roleId => new UserRole + { + TenantId = tenantId, + UserId = userId, + RoleId = roleId + }); + + await dbContext.UserRoles.AddRangeAsync(toAdd, cancellationToken); + await dbContext.SaveChangesAsync(cancellationToken); + + await trx.CommitAsync(cancellationToken); + }); } public Task SaveChangesAsync(CancellationToken cancellationToken = default)