我有一个以ProcessOrdersArgs为参数的服务,它可以包含数千个Order对象。我需要通过数据库服务器验证传入的每个订单都是存在的实际有效订单。现在,对于处理数千个订单的单个服务调用,我要对数据库进行数千次往返,只是为了验证传入的订单,我想大大减少数据库往返验证的次数。
我有以下相关的类用于我的验证。我的OrderValidator中的CustomerId和.OrderId是FluentValidation PropertyValidator类的扩展。
CustomerIdValidator内置了缓存,因为通常有数千个订单正在处理,其中许多是针对同一客户的,我想在验证同一CustomerId时减少往返数据库的次数。
我想对OrderId做一些类似的事情,并限制数据库往返的次数,但缓存不是解决方案,因为可能数千个OrderId中的每个OrderId都是唯一的。我想批量验证这些OrderId。我的想法是批量复制每个客户端的OrderId列表,并返回一个无效的OrderId(如果有的话)列表作为验证错误报告。
我该如何做到这一点,或者我是否需要另一种方法来构建我的验证,这样我就可以批量验证订单,而不是进行数千次往返数据库调用?
public class Order
{
public int CustomerId { get; set; }
public int OrderId { get; set; }
}
public class ProcessOrdersArgs
{
public List<Order> Orders { get; set; }
}
public class ProcessOrdersArgsValidator : AbstractValidator<ProcessOrdersArgs>
{
public ProcessOrdersArgsValidator(OrderValidator orderValidator)
{
RuleFor(a => a.Orders)
.SetCollectionValidator(orderValidator);
}
}
public class OrderValidator : AbstractValidator<Order>
{
public OrderValidator(DBConnection dbConnection)
{
RuleFor(c => c.CustomerId)
.CustomerId(dbConnection);
RuleFor(c => c.OrderId)
.OrderId(dbConnection, c => c.CustomerId);
}
}
您可以对Orders
属性使用谓词验证器Must
或MustAsync
public class ProcessOrdersArgsValidator : AbstractValidator<ProcessOrdersArgs>
{
public ProcessOrdersArgsValidator(DBConnection dbConnection)
{
RuleFor(a => a.Orders).Must(orders =>
{
var ids = orders.Select(o => o.OrderId);
return BulkValidateIds(ids, dbConnection);
});
}
private bool BulkValidateIds(IEnumerable<int> ids, DBConnection dbConnection)
....
}