流利的验证器来检查数据库中是否存在具有ID的实体

时间:2019-02-13 14:42:02

标签: servicestack fluentvalidation

我正在尝试编写一个自定义验证器,该验证器将使用OrmLite检查数据库中是否存在实体。问题在于,不能再通过使用来推断IRuleBuilder的类型参数。

我必须这样编写方法调用:

RuleFor(r => r.Id).Exists<DtoName, int, EntityName>()

但是我想这样写:

Rulefor(r => r.Id).Exists<EntityName>()

发生这种情况是因为IRuleBuilder具有两个类型参数,并且该方法是扩展方法。有没有一种聪明,流畅的方式来设计它并使函数调用最好像第二个版本一样?

这是我的扩展方法和验证器的代码:

    public static class AbstractValidatorExtensions
    {
        public static IRuleBuilderOptions<T, TProperty> Exists<T, TProperty, U>(this IRuleBuilder<T, TProperty> ruleBuilder)
        {
            return ruleBuilder.SetValidator(new EntityExistsValidator<U>());
        }                
    }

    public class EntityExistsValidator<T> : PropertyValidator
    {
        public EntityExistsValidator() : base("Entity does not exist") {}

        protected override bool IsValid(PropertyValidatorContext context)
        {
            return HostContext.Resolve<Repository>()
                .Exists<T>((int)context.PropertyValue);
        }
    }

2 个答案:

答案 0 :(得分:1)

您需要进行Custom Validator的自定义验证才能访问依赖项,例如:

RuleFor(x => x.Id)
    .Must(id =>
    {
        using (var db = HostContext.AppHost.GetDbConnection(base.Request))
        {
            return !db.Exists<EntityName>(x => x.Id == id);
        }
    })
    .WithErrorCode("AlreadyExists")
    .WithMessage("...");

我还将考虑只使用服务中的依赖项进行验证:

if (Db.Exists<EntityName>(x => x.Id == request.Id))
    throw new ArgumentException("Already Exists", nameof(request.Id));

答案 1 :(得分:0)

我对FluentValidation的经验是,您试图将越来越多的逻辑引入验证器中。我不会这样做,因为它增加了太多的复杂性。我的经验法则是仅验证离散属性值。示例:我只使用FluentValidation来检查int Id属性是否为0或大于0。检查该实体是否已经存在,我将转到另一个服务(通常称为“业务逻辑”)。