4

我想使用动态 LINQ 查询来搜索类中所有属性中的一些文本。我正在使用以下函数来创建表达式。我将属性名称和搜索文本传递给该方法。在该方法中,如果属性类型是 String,那么它工作正常。如果属性类型是 int、DateTime、GUID。然后它不工作。

我们知道 Contains 方法仅适用于元素数组或字符串。我认为属性的值应该类型转换为字符串。那么该怎么做呢?有解释的解决方案是帮助充分的。

我从这里收集了代码。

   public static Expression<Func<T, bool>> ContainsExp<T>(string propertyName, string contains)
    {
        var parameterExp = Expression.Parameter(typeof(T), "type");
        var propertyExp = Expression.Property(parameterExp, propertyName);

      MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });


        var someValue = Expression.Constant(contains, typeof(string));
        var containsMethodExp = Expression.Call(propertyExp, method, someValue);

        return Expression.Lambda<Func<T, bool>>(containsMethodExp, parameterExp);

    }
4

2 回答 2

2

好吧,您可能知道ToString()在 linq 中无法使用实体。

所以下面的问题是:如何将其他类型转换为字符串。

对于数值,你有SqlFunctions.StringConvert,但它只有double?和的重载decimal?

对于DateTime,您可能会SqlFunctions.StringConvert在申请后找到使用SqlFunctions.DatePart的东西DateTime(这可能意味着至少 3 次调用SqlFunctions.DatePart,代表年、月、日)

对于Guid,我认为没有办法直接做到这一点。一种方法(在 db 级别,如果您使用 Sql Server)可能是拥有一个 Computed 列。计算列可以存储您的 GUID 的 varchar 转换表示。也许有更好的方法。

无论如何,这里至少有一个样本应该适用integerstring

 public static Expression<Func<T, bool>> ContainsExp<T>(string propertyName, string contains)
        {

            //first, get the type of your property
            var propertyType = typeof(T).GetProperty(propertyName).PropertyType;
            //no change
            var parameterExp = Expression.Parameter(typeof (T), "type");
            Expression propertyExp = Expression.Property(parameterExp, propertyName);
            //if property's type is int
            if (propertyType == typeof (int))
            {
                //convert your Expression to a nullable double (or nullable decimal),
                //so that you can use SqlFunctions.StringConvert
                propertyExp = Expression.Convert(propertyExp, typeof (double?));
                //get the SqlFunctions.StringConvert method for nullable double
                var stringConvertMethod = typeof (SqlFunctions).GetMethod("StringConvert", new[] {typeof (double?)});
                //call StringConvert on your converted expression
                propertyExp = Expression.Call(stringConvertMethod , propertyExp);
            }
            //no change
            var method = typeof (string).GetMethod("Contains", new[] {typeof (string)});


            var someValue = Expression.Constant(contains, typeof (string));
            var containsMethodExp = Expression.Call(propertyExp, method, someValue);

            return Expression.Lambda<Func<T, bool>>(containsMethodExp, parameterExp);

        }
于 2013-10-11T13:01:17.970 回答
0
 public static IQueryable<T> FieldsContains<T>(this IQueryable<T> query, List<string> fileds, string searchValue)
    {
        Expression predicate = null;
        var parameterExpression = Expression.Parameter(typeof(T), "type");

        foreach (string field in fileds)
        {
            var next = GetFieldContainsExpression<T>(parameterExpression, field, searchValue);

            if (predicate == null)
            {
                predicate = next;
            }
            else
            {
                predicate = Expression.Or(predicate, next);
            }
        }

        var lambda = Expression.Lambda<Func<T, bool>>(predicate, parameterExpression);

        return query.Where(lambda);
    }

    private static Expression GetFieldContainsExpression<T>(ParameterExpression parameterExpression, string field, string value)
    {
        var propertyType = typeof(T).GetProperty(field).PropertyType;
        Expression propertyExpression = Expression.Property(parameterExpression, field);

        var filterValue = Expression.Constant(value);
        var method = typeof(string).GetMethod("Contains", new[] { typeof(string) });

        //call toString first to ignore type errors(datetime, int ...)
        var toStringExpression = Expression.Call(propertyExpression, "ToString", Type.EmptyTypes);
        var containsExpression = Expression.Call(toStringExpression, method, filterValue);

        return containsExpression;
    }
于 2019-05-19T15:26:13.680 回答