From ec5293d892eaacb4ebbed1195c20e1dd81129099 Mon Sep 17 00:00:00 2001 From: MSuMshk <2039814060@qq.com> Date: Fri, 6 Feb 2026 12:11:52 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20identity=20=E7=99=BB=E5=BD=95=E5=B9=B6?= =?UTF-8?q?=E5=8F=91=E6=94=B9=E4=B8=BA=20xmin?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 移除 identity_users 对 RowVersion 列的依赖,改用 PostgreSQL xmin 作为并发令牌,修复线上登录因缺失 RowVersion 列导致的 500 错误。 --- .../Identity/Commands/UpdateIdentityUserCommand.cs | 6 ++---- .../Handlers/UpdateIdentityUserCommandHandler.cs | 1 - .../Validators/UpdateIdentityUserCommandValidator.cs | 1 - .../Identity/Persistence/IdentityDbContext.cs | 10 ++++++---- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/Application/TakeoutSaaS.Application/Identity/Commands/UpdateIdentityUserCommand.cs b/src/Application/TakeoutSaaS.Application/Identity/Commands/UpdateIdentityUserCommand.cs index 9fd7734..1aeb098 100644 --- a/src/Application/TakeoutSaaS.Application/Identity/Commands/UpdateIdentityUserCommand.cs +++ b/src/Application/TakeoutSaaS.Application/Identity/Commands/UpdateIdentityUserCommand.cs @@ -50,9 +50,7 @@ public sealed record UpdateIdentityUserCommand : IRequest public string[]? RoleIds { get; init; } /// - /// 并发控制版本。 + /// 并发控制版本(兼容字段,当前由数据库 xmin 托管)。 /// - [Required] - [MinLength(1)] - public byte[] RowVersion { get; init; } = Array.Empty(); + public byte[]? RowVersion { get; init; } } diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateIdentityUserCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateIdentityUserCommandHandler.cs index 81a812b..665ee40 100644 --- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateIdentityUserCommandHandler.cs +++ b/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateIdentityUserCommandHandler.cs @@ -87,7 +87,6 @@ public sealed class UpdateIdentityUserCommandHandler( user.Phone = phone; user.Email = email; user.Avatar = string.IsNullOrWhiteSpace(request.Avatar) ? null : request.Avatar.Trim(); - user.RowVersion = request.RowVersion; // 6. 构建操作日志消息 var operatorName = string.IsNullOrWhiteSpace(operatorProfile.DisplayName) diff --git a/src/Application/TakeoutSaaS.Application/Identity/Validators/UpdateIdentityUserCommandValidator.cs b/src/Application/TakeoutSaaS.Application/Identity/Validators/UpdateIdentityUserCommandValidator.cs index cfa600b..44ce8f1 100644 --- a/src/Application/TakeoutSaaS.Application/Identity/Validators/UpdateIdentityUserCommandValidator.cs +++ b/src/Application/TakeoutSaaS.Application/Identity/Validators/UpdateIdentityUserCommandValidator.cs @@ -16,7 +16,6 @@ public sealed class UpdateIdentityUserCommandValidator : AbstractValidator x.UserId).GreaterThan(0); RuleFor(x => x.DisplayName).NotEmpty().MaximumLength(64); RuleFor(x => x.Avatar).MaximumLength(512); - RuleFor(x => x.RowVersion).NotEmpty(); RuleFor(x => x.TenantId).GreaterThan(0).When(x => x.TenantId.HasValue); RuleForEach(x => x.RoleIds) .Must(value => long.TryParse(value, out _)) diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/IdentityDbContext.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/IdentityDbContext.cs index 4efefe2..818fe13 100644 --- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/IdentityDbContext.cs +++ b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/IdentityDbContext.cs @@ -104,10 +104,12 @@ public sealed class IdentityDbContext( builder.Property(x => x.LastLoginAt); builder.Property(x => x.MustChangePassword).IsRequired(); builder.Property(x => x.Avatar).HasColumnType("text"); - builder.Property(x => x.RowVersion) - .IsRowVersion() - .IsConcurrencyToken() - .HasColumnType("bytea"); + builder.Ignore(x => x.RowVersion); + builder.Property("xmin") + .HasColumnName("xmin") + .HasColumnType("xid") + .ValueGeneratedOnAddOrUpdate() + .IsConcurrencyToken(); builder.Property(x => x.TenantId).IsRequired(); ConfigureAuditableEntity(builder); ConfigureSoftDeleteEntity(builder);