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