0

我有表达式助手类,用于服务器端过滤我动态检查的列名,例如:

 public static Expression<Func<TItem, bool>> PropertyContains<TItem>(PropertyInfo propertyInfo, string value)
    {
        var param = Expression.Parameter(typeof(TItem));

        var m = Expression.MakeMemberAccess(param, propertyInfo);
        var c = Expression.Constant(value, typeof(string));
        var mi = typeof(string).GetMethod("Contains", new Type[] { typeof(string) });
        var body = Expression.Call(m, mi, c);

        return Expression.Lambda<Func<TItem, bool>>(body, param);
    }

这个工作得很好。我还有另一个静态辅助方法来比较值是否相等:

 public static Expression<Func<TItem, bool>> PropertyEquals<TItem, TValue>(
            PropertyInfo property, TValue value)
        {
            var param = Expression.Parameter(typeof(TItem));
            var xx = Expression.Property(param, property);
            var body = Expression.Equal(Expression.Property(param, property),
                Expression.Constant(value));
            return Expression.Lambda<Func<TItem, bool>>(body, param);
        }

这也很好用。

但是,对于小数字段(Decimal(19,4)在 SQL 中),我遇到的问题是,用户只能在 UI 上看到 2 位数字作为小数位让我们说 $19.32 所以当他们在搜索字段中输入 19.32 时,它与作为记录的 db 记录不匹配在 db 中实际上是 19.3224 可以说。数学上如此19.32 != 19.3224,但由于我在 UI 上只显示 2 个小数位,它不会返回用户正在寻找的记录。

我的问题是,我不确定如何在 Expression 中操作 db 记录的值。甚至现在使用 Decimal.Truncate 就足够了(这意味着如果我忽略小数位并只比较 int 部分就可以了)

我尝试了如下方法:

 public static Expression<Func<TItem, bool>> PropertyEqualMoneyFields<TItem>(PropertyInfo propertyInfo, decimal value) 
        {
            var param = Expression.Parameter(typeof(TItem));

            var m = Expression.MakeMemberAccess(param, propertyInfo);
            var c = Expression.Constant(value, typeof(decimal));
            var mi = typeof(decimal).GetMethod("Truncate", new Type[] { typeof(decimal) });
            var body = Expression.Call(m, mi, c);
            return Expression.Lambda<Func<TItem, bool>>(body, param); 
        }

我称之为:

string filteredColumnNameInDb = "SomeMoneyColumnName"; // coming from ui actually
 PropertyInfo filteredProperty = typeof(SomeDto).GetProperty(filteredColumnNameInDb);
 query = query.Where(ExpressionHelper.PropertyEqualMoneyFields<SomeDto>filteredProperty,decimal.Truncate(decimalValue)));

但它会抛出一个异常Static method requires null instance, non-static method requires non-null instance.,即使没有异常,这也不会起作用,因为我仍然需要Expression.Equal在某些时候应用来比较它们在截断后是否相等。

如果我完全不采用这种方法,我很想听听任何其他方法来做到这一点。

或者,如果不清楚,如果有人可以指出“在进行任何比较之前在 db 记录上运行 sql 函数”,那将非常有用,所以也许我会创建一些 sql 函数先应用于该记录,然后进行Expression.Equal比较。

PS:我知道我可以在 ToList() 之后轻松做到这一点,但这是服务器端过滤的重点,因为我不想加载整个数据集!

4

0 回答 0