4

ダイナミック LINQ クエリを使用して、クラス内のすべてのプロパティのテキストを検索したいと考えています。次の関数を使用して式を作成しています。プロパティ名と検索テキストをメソッドに渡しています。そのメソッドでは、プロパティ タイプが String の場合、正常に動作しています。プロパティの型が int、DateTime、GUID の場合。それは機能していません。

ご存知のように、Contains メソッドは要素の配列または文字列に対してのみ使用されます。プロパティの値は、文字列にキャストする必要があると考えています。では、どうすればよいのでしょうか? 説明付きの解決策はヘルプフルです。

i thisからコードを収集しました。

   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(これはSqlFunctions.DatePart、年、月、日の少なくとも 3 回の呼び出しを意味します)

Guidの場合、直接行う方法はないと思います。1 つの方法 (SQL Server を使用する場合は db レベルで) は、Computed 列を持つことです。計算列には、GUID の varchar 変換された表現を格納できます。たぶんもっと良い方法があります。

とにかく、ここに少なくともinteger同様に機能するはずのサンプルがありますstring

 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 に答える