FluentValidation规则间参数传递问题:后续规则提前执行致值为空
解决FluentValidation异步规则执行顺序导致的依赖值为空问题
我之前也踩过这个坑!FluentValidation的规则默认是并行评估的,尤其是异步规则,第二条规则根本不等第一条查库完成就执行了,自然Values还是null。给你几个不用重复查询数据库的解决方案:
方案1:用DependentRules强制规则顺序执行
这是最直接的方法,FluentValidation的DependentRules就是专门用来处理“只有当前规则通过后,才执行后续依赖规则”的场景。修改后的代码如下:
private SomeValue Values; RuleFor(x => x.id) .Cascade(CascadeMode.StopOnFirstFailure) .MustAsync(async (id, cancellationToken) => { var test = await dbContext.Set<Foo>().FirstOrDefaultAsync(x => x.Id == id); Values = test?.Value; // 加个空判断避免空引用 return test != null; }) // 把依赖的规则放到DependentRules里,确保只有第一条规则通过才会执行 .DependentRules(() => { RuleFor(x => x.Values).MustFindAllMandatory(Values); });
这样第一条异步规则执行完成并验证通过后,才会触发DependentRules里的第二条规则,此时Values已经被正确赋值了。
方案2:合并逻辑到同一个异步规则中
如果DependentRules的方式不符合你的需求,或者你想更紧凑地处理验证逻辑,可以把两个验证步骤合并到同一个MustAsync里,这样只查一次数据库,而且完全避免顺序问题:
RuleFor(x => x.id) .Cascade(CascadeMode.StopOnFirstFailure) .MustAsync(async (id, context, cancellationToken) => { var test = await dbContext.Set<Foo>().FirstOrDefaultAsync(x => x.Id == id); // 第一步:验证ID是否存在 if (test == null) { context.AddFailure("id", "指定的ID不存在"); return false; } // 第二步:验证Values是否符合要求 bool isValuesValid = MustFindAllMandatory(test.Value); // 假设这是一个可直接调用的方法 if (!isValuesValid) { context.AddFailure("Values", "Values不符合必填项要求"); return false; } return true; });
这种方式的好处是可以更灵活地自定义错误信息,而且完全不需要依赖外部变量传递值,避免了并发赋值的问题。
方案3:用WhenAsync配合状态检查(不推荐)
虽然WhenAsync可以用来控制规则的执行时机,但因为规则是并行评估的,它无法保证在第一条规则完成后才执行,除非你在WhenAsync里重复查询数据库(这正是你不想做的),所以这个方法优先级最低,仅作参考:
private SomeValue Values; RuleFor(x => x.id) .Cascade(CascadeMode.StopOnFirstFailure) .MustAsync(async (id, cancellationToken) => { var test = await dbContext.Set<Foo>().FirstOrDefaultAsync(x => x.Id == id); Values = test?.Value; return test != null; }); RuleFor(x => x.Values) .MustFindAllMandatory(Values) .WhenAsync(async (model, cancellationToken) => { // 这里只能判断Values是否已赋值,但无法保证是第一条规则执行后的结果 return Values != null; });
总结
优先推荐方案1,它是FluentValidation官方设计用来处理规则依赖的特性,代码清晰且符合框架设计思路;如果需要更灵活的错误处理,方案2会是更好的选择。
内容的提问来源于stack exchange,提问作者tri
相关产品推荐
相关产品推荐

