我的产品系列包含一个日期范围列表,表示租用产品的日期。所以它看起来像这样:
"product" : {
...
"RentalPeriods" : [
{
"From" : ISODate("2017-02-11T23:00:00.000Z"),
"To" : ISODate("2017-02-12T23:00:00.000Z")
},
{
"From" : ISODate("2017-10-09T23:00:00.000Z"),
"To" : ISODate("2017-10-21T23:00:00.000Z")
}
]
...
}
我想创建将遍历所有产品的查询,并且只返回可以在提供的日期范围内租用的产品。 所以,如果我提供类似的东西:
RentalPeriod(" 2017-03-03"," 2017-03-04") - 它应该返回上面的产品
RentalPeriod(" 2017-02-03"," 2017-02-14") - 它不应该返回上面的产品
我们尝试使用LINQ表达式,但是我们得到了不支持的过滤器异常。
所以这就是我们的尝试:
public Expression<Func<Product, bool>> IsSatisfied() =>
product => product.RentalPeriods.All(rentPeriod => !(_fromDate > rentPeriod.FromDate && _fromDate < rentPeriod.MaybeToDate.Value) &&
!(rentPeriod.FromDate > _fromDate && rentPeriod.FromDate < _toDate));
(以上查询是部分的,但我想我们尝试的很清楚。)
还有其他方法可以实现这一目标吗?
修改13-12-2017 :
public class AvailabilityForRentalPeriodSpecification : ISpecification<Product>
{
private UtcDate _fromDate;
private UtcDate _toDate;
public AvailabilityForRentalPeriodSpecification(RentalPeriod rentalPeriod)
{
_fromDate = rentalPeriod.FromDate;
_toDate = rentalPeriod.MaybeToDate.Value;
}
public Expression<Func<Product, bool>> IsSatisfied() =>
product => product.RentalPeriods.All(rentPeriod => !(_fromDate > rentPeriod.FromDate && _fromDate < rentPeriod.MaybeToDate.Value) &&
!(rentPeriod.FromDate > _fromDate && rentPeriod.FromDate < _toDate));
}
此规范在DAO层中用作:
public IList<T> GetBy(ISpecification<T> specification)
=> _mongoCollection.Find(specification.IsSatisfied()).ToList();
可能的解决方案(我试图避免)是从数据库中检索所有产品,然后在代码中过滤它们。
答案 0 :(得分:0)
我更改了一个查询逻辑,使用 Any 方法而不是不支持的 All 方法,所以它现在看起来像这样:
public Expression<Func<Product, bool>> IsSatisfied() =>
product => !product.RentalPeriods.Any(dbRentalPeriod => _fromDate >= dbRentalPeriod.FromDate && _fromDate <= dbRentalPeriod.ToDate ||
_toDate >= dbRentalPeriod.FromDate && _toDate <= dbRentalPeriod.ToDate ||
dbRentalPeriod.FromDate >= _fromDate && dbRentalPeriod.ToDate <= _toDate);
另一个问题是使用Maybe struct for ToDate (rentPeriod.MaybeToDate.Value),这是通过在MaybeToDate字段旁边创建内部DateTime字段来解决的。