使用 BinaryExpression 解析 DateTime 的日期部分



我已经找到了类似概念的答案,但似乎都不适合我的情况。

我正在构建一个对象,该对象通过 Where 子句和运行时已知类型的 Lambda 过滤结果。

过滤器

数组可以包含一个或多个过滤器,这些过滤器具有属性名称和相等运算符(即 gte、eq、neq 等)和要比较的值。

由于我可以有多个属性要过滤,因此我首先获取比较任何对象属性所需的所有 BinaryExpression并将它们合并到传递给查询 Where 子句的单个表达式中。

如果筛选器的属性类型是 DateTime,我只想使用 BinaryExpression 比较属性的 Date 部分。

我有一个接收过滤器的参数名称及其值的方法。

public static Expression<Func<T, bool>> GetEqualExpression<T>(string parameterName,
            string comparisonValue) {
    var param = Expression.Parameter(typeof(T), parameterName);
    var property = Expression.Property(param, parameterName);
    var propInfo = (PropertyInfo) property.Member;
    var propType = propInfo.PropertyType;
    if (propType == typeof(DateTime)) {
        // Parse the string to a DateTime.
        const string dateFormat = "ddd MMM d yyyy HH:mm:ss 'GMT'K";
        var parsedDate = DateTime.ParseExact(comparisonValue, dateFormat, CultureInfo.InvariantCulture); 
        // Trying to access the 'Date' child property.
        property = Expression.Property(property, "Date");
        var constant = Expression.Constant(parsedDate.Date);

        return Expression.Lambda<Func<T, bool>>(Expression.Equal(property, constant), param);
    }
    ...
}

例如,将对象视为:

public class Ticket {
    public DateTime StartDate {get; set;}
    public DateTime DueDate {get; set;}
}

以及"StartDate"属性的过滤器,当我将表达式传递给查询的 where 子句时,它会失败并出现异常"Lambda 参数不在范围内"。

我错过了什么?

提前谢谢你。

更新

因此,多亏了xanatos,我发现ServiceStack.OrmLite(我正在使用的ORM)不支持访问Date属性,就像EF一样。所以现在的问题是,我该如何解决这种情况?

所以,这就是我处理这种情况的方式。我真的要感谢xanatos指出ORM的DateTime.Date问题。

我决定通过以下方式按时间范围比较日期相等性:

public static Expression<Func<T, bool>> GetEqualExpression(string parameterName, 
    string comparisonValue)
{
    var param = Expression.Parameter(typeof (T), parameterName);
    var prop = Expression.Property(param, parameterName);
    var propInfo = (PropertyInfo) Property.Member;
    var propType = propInfo.PropertyType;
    if (propType == typeof(DateTime))
    {
        const string dateFormat = "ddd MMM d yyyy HH:mm:ss 'GMT'K";
        var parsedDate = DateTime.ParseExact(comparisonValue, dateFormat, CultureInfo.InvariantCulture);
        var dayStart = new DateTime(parsedDate.Year, parsedDate.Month, parsedDate.Day, 0, 0, 0, 0);
        var dayEnd = new DateTime(parsedDate.Year, parsedDate.Month, parsedDate.Day, 23, 59, 59, 999);
        var left = Expression.Lambda<Func<T, bool>>(Expression.GreaterThanOrEqual(prop, Expression.Constant(dayStart)), param);
        var right = Expression.Lambda<Func<T, bool>>(Expression.LessThanOrEqual(prop, Expression.Constant(dayEnd)), param);
        return left.Compose(right, Expression.And);
    }
    ...
}

这似乎可以解决问题。

有一个小错误:你必须使用

Expression.Equal(property, constant)

而不是

Expression.Equals(property, constant)

然后,也许您在 由于我可以有多个属性要过滤,因此我首先获取所有需要比较任何对象属性的 BinaryExpression 并将它们合并到传递给查询 Where 子句部分的单个表达式中

请注意,如果您使用的是实体框架,则可能不支持该DateTime.Date。请参阅 https://stackoverflow.com/a/21186498/613130 。一种可能的解决方案是使用 EntityFunctions.TruncateTime .

相关内容

  • 没有找到相关文章

最新更新