chore: 🔨 参数配置忽略版本锁 (#138)

[skip ci]

Co-authored-by: tk <fiyne1a@dingtalk.com>
This commit is contained in:
nsnail 2024-06-07 11:05:05 +08:00 committed by GitHub
parent 56b111b1cf
commit 366ca0d237
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 58 additions and 31 deletions

View File

@ -65,7 +65,6 @@
登录 登录
硕士 硕士
离异 离异
私信
空闲 空闲
等于 等于
等待发送 等待发送

View File

@ -34,18 +34,15 @@ XML注释文件不存在
数据库同步开始 数据库同步开始
数据库服务器时钟偏移 数据库服务器时钟偏移
数据库结构同步完成 数据库结构同步完成
数据版本不能为空
文件不能为空 文件不能为空
新密码不能为空 新密码不能为空
新手机号码验证码不正确 新手机号码验证码不正确
无效端口号 无效端口号
无效证件号码 无效证件号码
日志长度超过限制
旧密码不正确 旧密码不正确
旧密码不能为空 旧密码不能为空
旧手机号码不正确 旧手机号码不正确
旧手机号码验证码不正确 旧手机号码验证码不正确
时间戳缺失或误差过大
时间表达式 时间表达式
时间计划不能为空 时间计划不能为空
未指定部门 未指定部门
@ -62,7 +59,6 @@ XML注释文件不存在
用户名或密码错误 用户名或密码错误
用户名长度4位以上 用户名长度4位以上
用户头像不能为空 用户头像不能为空
用户档案不能为空
用户编号不存在 用户编号不存在
用户编号不能为空 用户编号不能为空
目标设备不能为空 目标设备不能为空
@ -70,7 +66,6 @@ XML注释文件不存在
站内信不存在 站内信不存在
站内信状态不正确 站内信状态不正确
站内信类型不正确 站内信类型不正确
签名缺失
网络地址不正确 网络地址不正确
菜单名称不能为空 菜单名称不能为空
菜单标题不能为空 菜单标题不能为空

View File

@ -1,4 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<DefineConstants>DBTYPE_SQLITE</DefineConstants>
</PropertyGroup>
<Import Project="$(SolutionDir)/build/code.quality.props"/> <Import Project="$(SolutionDir)/build/code.quality.props"/>
<ItemGroup> <ItemGroup>
<ProjectReference Include="../NetAdmin.SysComponent.Application/NetAdmin.SysComponent.Application.csproj"/> <ProjectReference Include="../NetAdmin.SysComponent.Application/NetAdmin.SysComponent.Application.csproj"/>

View File

@ -1,4 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<DefineConstants>DBTYPE_SQLITE</DefineConstants>
</PropertyGroup>
<Import Project="$(SolutionDir)/build/code.quality.props"/> <Import Project="$(SolutionDir)/build/code.quality.props"/>
<ItemGroup> <ItemGroup>
<ProjectReference Include="../NetAdmin.Domain/NetAdmin.Domain.csproj"/> <ProjectReference Include="../NetAdmin.Domain/NetAdmin.Domain.csproj"/>

View File

@ -31,43 +31,68 @@ public abstract class RepositoryService<TEntity, TPrimary, TLogger>(BasicReposit
/// <summary> /// <summary>
/// 更新实体 /// 更新实体
/// </summary> /// </summary>
protected Task<int> UpdateAsync(TEntity dto, IEnumerable<string> includeFields, string[] excludeFields = null /// <param name="newValue">新的值</param>
, Expression<Func<TEntity, bool>> whereExp = null) /// <param name="includeFields">包含的属性</param>
/// <param name="excludeFields">排除的属性</param>
/// <param name="whereExp">查询表达式</param>
/// <param name="ignoreVersion">是否忽略版本锁</param>
/// <returns>更新行数</returns>
protected Task<int> UpdateAsync( //
TEntity newValue //
, IEnumerable<string> includeFields //
, string[] excludeFields = null //
, Expression<Func<TEntity, bool>> whereExp = null //
, bool ignoreVersion = false)
{ {
whereExp ??= a => a.Id.Equals(dto.Id); // 默认匹配主键
var update = BuildUpdate(dto, includeFields, excludeFields).Where(whereExp); whereExp ??= a => a.Id.Equals(newValue.Id);
var update = BuildUpdate(newValue, includeFields, excludeFields, ignoreVersion).Where(whereExp);
return update.ExecuteAffrowsAsync(); return update.ExecuteAffrowsAsync();
} }
#if DBTYPE_SQLSERVER #if DBTYPE_SQLSERVER
/// <summary> /// <summary>
/// 更新实体 /// 更新实体
/// </summary> /// </summary>
protected Task<List<TEntity>> UpdateEntityAsync(TEntity dto, IEnumerable<string> includeFields /// <param name="newValue">新的值</param>
, string[] excludeFields = null /// <param name="includeFields">包含的属性</param>
, Expression<Func<TEntity, bool>> whereExp = null) /// <param name="excludeFields">排除的属性</param>
/// <param name="whereExp">查询表达式</param>
/// <param name="ignoreVersion">是否忽略版本锁</param>
/// <returns>更新后的实体列表</returns>
protected Task<List<TEntity>> UpdateReturnListAsync( //
TEntity newValue //
, IEnumerable<string> includeFields //
, string[] excludeFields = null //
, Expression<Func<TEntity, bool>> whereExp = null //
, bool ignoreVersion = false)
{ {
whereExp ??= a => a.Id.Equals(dto.Id); // 默认匹配主键
return BuildUpdate(dto, includeFields, excludeFields).Where(whereExp).ExecuteUpdatedAsync(); whereExp ??= a => a.Id.Equals(newValue.Id);
return BuildUpdate(newValue, includeFields, excludeFields, ignoreVersion).Where(whereExp).ExecuteUpdatedAsync();
} }
#endif #endif
private IUpdate<TEntity> BuildUpdate(TEntity dto, IEnumerable<string> includeFields, string[] excludeFields = null) private IUpdate<TEntity> BuildUpdate( //
TEntity entity //
, IEnumerable<string> includeFields //
, string[] excludeFields = null //
, bool ignoreVersion = false)
{ {
var ret = includeFields == null var updateExp = includeFields == null
? Rpo.UpdateDiy.SetSource(dto) ? Rpo.UpdateDiy.SetSource(entity)
: Rpo.UpdateDiy.SetDto(includeFields!.ToDictionary( : Rpo.UpdateDiy.SetDto(includeFields!.ToDictionary(
x => x x => x
, x => typeof(TEntity).GetProperty(x, BindingFlags.Public | BindingFlags.Instance)! , x => typeof(TEntity).GetProperty(x, BindingFlags.Public | BindingFlags.Instance)!
.GetValue(dto))); .GetValue(entity)));
if (excludeFields != null) { if (excludeFields != null) {
ret = ret.IgnoreColumns(excludeFields); updateExp = updateExp.IgnoreColumns(excludeFields);
} }
if (dto is IFieldVersion version) { if (!ignoreVersion && entity is IFieldVersion ver) {
ret = ret.Where($"{nameof(IFieldVersion.Version)} = @version", new { version = version.Version }); updateExp = updateExp.Where($"{nameof(IFieldVersion.Version)} = @version", new { version = ver.Version });
} }
return ret; return updateExp;
} }
} }

View File

@ -10,11 +10,9 @@ public sealed record EditRoleReq : CreateRoleReq
{ {
/// <inheritdoc cref="EntityBase{T}.Id" /> /// <inheritdoc cref="EntityBase{T}.Id" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)] [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
[Required(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.唯一编码不能为空))]
public override long Id { get; init; } public override long Id { get; init; }
/// <inheritdoc cref="IFieldVersion.Version" /> /// <inheritdoc cref="IFieldVersion.Version" />
[JsonIgnore(Condition = JsonIgnoreCondition.Never)] [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
[Required(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.数据版本不能为空))]
public override long Version { get; init; } public override long Version { get; init; }
} }

View File

@ -1,4 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<DefineConstants>DBTYPE_SQLITE</DefineConstants>
</PropertyGroup>
<Import Project="$(SolutionDir)/build/code.quality.props"/> <Import Project="$(SolutionDir)/build/code.quality.props"/>
<ItemGroup> <ItemGroup>
<ProjectReference Include="../NetAdmin.Application/NetAdmin.Application.csproj"/> <ProjectReference Include="../NetAdmin.Application/NetAdmin.Application.csproj"/>

View File

@ -55,7 +55,7 @@ public sealed class ConfigService(BasicRepository<Sys_Config, long> rpo) //
public async Task<QueryConfigRsp> EditAsync(EditConfigReq req) public async Task<QueryConfigRsp> EditAsync(EditConfigReq req)
{ {
#if DBTYPE_SQLSERVER #if DBTYPE_SQLSERVER
return (await UpdateEntityAsync(req, null).ConfigureAwait(false)).FirstOrDefault()?.Adapt<QueryConfigRsp>(); return (await UpdateReturnListAsync(req, null).ConfigureAwait(false)).FirstOrDefault()?.Adapt<QueryConfigRsp>();
#else #else
return await UpdateAsync(req, null).ConfigureAwait(false) > 0 return await UpdateAsync(req, null).ConfigureAwait(false) > 0
? await GetAsync(new QueryConfigReq { Id = req.Id }).ConfigureAwait(false) ? await GetAsync(new QueryConfigReq { Id = req.Id }).ConfigureAwait(false)

View File

@ -73,7 +73,7 @@ public sealed class DeptService(BasicRepository<Sys_Dept, long> rpo) //
public async Task<QueryDeptRsp> EditAsync(EditDeptReq req) public async Task<QueryDeptRsp> EditAsync(EditDeptReq req)
{ {
#if DBTYPE_SQLSERVER #if DBTYPE_SQLSERVER
return (await UpdateEntityAsync(req, null).ConfigureAwait(false)).FirstOrDefault()?.Adapt<QueryDeptRsp>(); return (await UpdateReturnListAsync(req, null).ConfigureAwait(false)).FirstOrDefault()?.Adapt<QueryDeptRsp>();
#else #else
return await UpdateAsync(req, null).ConfigureAwait(false) > 0 return await UpdateAsync(req, null).ConfigureAwait(false) > 0
? await GetAsync(new QueryDeptReq { Id = req.Id }).ConfigureAwait(false) ? await GetAsync(new QueryDeptReq { Id = req.Id }).ConfigureAwait(false)

View File

@ -74,7 +74,8 @@ public sealed class DicContentService(BasicRepository<Sys_DicContent, long> rpo)
} }
#if DBTYPE_SQLSERVER #if DBTYPE_SQLSERVER
return (await UpdateEntityAsync(req, null).ConfigureAwait(false)).FirstOrDefault()?.Adapt<QueryDicContentRsp>(); return (await UpdateReturnListAsync(req, null).ConfigureAwait(false)).FirstOrDefault()
?.Adapt<QueryDicContentRsp>();
#else #else
return await UpdateAsync(req, null).ConfigureAwait(false) > 0 return await UpdateAsync(req, null).ConfigureAwait(false) > 0
? await GetAsync(new QueryDicContentReq { Id = req.Id }).ConfigureAwait(false) ? await GetAsync(new QueryDicContentReq { Id = req.Id }).ConfigureAwait(false)

View File

@ -193,7 +193,7 @@ public sealed class JobService(BasicRepository<Sys_Job, long> rpo, IJobRecordSer
} }
#if DBTYPE_SQLSERVER #if DBTYPE_SQLSERVER
var ret = await UpdateEntityAsync( // var ret = await UpdateReturnListAsync( //
job with { Status = JobStatues.Running, LastExecTime = DateTime.Now } job with { Status = JobStatues.Running, LastExecTime = DateTime.Now }
, [nameof(job.Status), nameof(job.LastExecTime)]) , [nameof(job.Status), nameof(job.LastExecTime)])
.ConfigureAwait(false); .ConfigureAwait(false);

View File

@ -60,7 +60,7 @@ public sealed class MenuService(BasicRepository<Sys_Menu, long> rpo, IUserServic
public async Task<QueryMenuRsp> EditAsync(EditMenuReq req) public async Task<QueryMenuRsp> EditAsync(EditMenuReq req)
{ {
#if DBTYPE_SQLSERVER #if DBTYPE_SQLSERVER
return (await UpdateEntityAsync(req, null).ConfigureAwait(false)).FirstOrDefault()?.Adapt<QueryMenuRsp>(); return (await UpdateReturnListAsync(req, null).ConfigureAwait(false)).FirstOrDefault()?.Adapt<QueryMenuRsp>();
#else #else
return await UpdateAsync(req, null).ConfigureAwait(false) > 0 return await UpdateAsync(req, null).ConfigureAwait(false) > 0
? await GetAsync(new QueryMenuReq { Id = req.Id }).ConfigureAwait(false) ? await GetAsync(new QueryMenuReq { Id = req.Id }).ConfigureAwait(false)