2013-09-02 2 views
0

После успешной реализации подобной функции с использованием строковой функции «содержит» я заметил, что при переходе на sql маскируются экраны.EF Dynamic Query - Like

Например. Когда я ищу улицу, начинающуюся с p, в ней есть номер 13. Я заменяю все пространство на «%», но EF ускользает от него. Выходной запрос выглядит следующим образом:

SELECT " FROM Customer WHERE (LOWER([Street]) LIKE N'%p~%13%' ESCAPE N'~') 

В одном из блогов было предложено использовать patindex. Я просто не знаю, как это реализовать.

Мой текущий код выглядит следующим образом:

public static Expression<Func<T, bool>> Create<T>(string propertyName, ComparisonOperators comparisonOperator, dynamic comparedValue1, dynamic comparedValue2 = null) 
{ 
    ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "x"); 
    MemberExpression memberExpression = Expression.MakeMemberAccess(parameterExpression, typeof(T).GetProperty(propertyName)); 
    ConstantExpression constantExpression = Expression.Constant(comparedValue1, comparedValue1.GetType()); 
    Expression expressionBody = null; 

    switch (comparisonOperator) 
    { 
     ... 

     case ComparisonOperators.Contains: 
      expressionBody = Expression.Call(GetLowerCasePropertyAccess(memberExpression), ContainsMethod, Expression.Constant(comparedValue1.ToLower())); 
      break; 
    } 

    return Expression.Lambda<Func<T, bool>>(expressionBody, new ParameterExpression[] { parameterExpression }); 
} 

private static MethodCallExpression GetLowerCasePropertyAccess(MemberExpression propertyAccess) 
{ 
    var stringExpression = GetConvertToStringExpression(propertyAccess); 
    if (stringExpression == null) 
     throw new Exception(string.Format("Not supported property type {0}", propertyAccess.Type)); 

    return Expression.Call(stringExpression, typeof(string).GetMethod("ToLower", Type.EmptyTypes)); 
} 

private static Expression GetConvertToStringExpression(Expression e) 
{ 
    // if property string - no cast needed 
    // else - use SqlFunction.StringConvert(double?) or SqlFunction.StringConvert(decimal?); 
    Expression strExpression = null; 
    if (e.Type == typeof(string)) strExpression = e; 
    else 
    { 
     var systemType = Nullable.GetUnderlyingType(e.Type) ?? e.Type; 
     if (systemType == typeof(int) || systemType == typeof(long) || systemType == typeof(double) || systemType == typeof(short) || systemType == typeof(byte)) 
     { 
      // cast int to double 
      var doubleExpr = Expression.Convert(e, typeof(double?)); 
      strExpression = Expression.Call(StringConvertMethodDouble, doubleExpr); 
     } 
     else if (systemType == typeof(decimal)) 
     { 
      // call decimal version of StringConvert method 
      // cast to nullable decimal 
      var decimalExpr = Expression.Convert(e, typeof(decimal?)); 
      strExpression = Expression.Call(StringConvertMethodDecimal, decimalExpr); 
     } 
    } 
    return strExpression; 
} 

private static readonly MethodInfo ContainsMethod = typeof(String).GetMethod("Contains", new Type[] { typeof(String) }); 
private static readonly MethodInfo StringConvertMethodDouble = typeof(SqlFunctions).GetMethod("StringConvert", new Type[] { typeof(double?) }); 
private static readonly MethodInfo StringConvertMethodDecimal = typeof(SqlFunctions).GetMethod("StringConvert", new Type[] { typeof(decimal?) }); 

ответ

0

Как это:

ctx.Products.Where(x => SqlFunctions.PatIndex("%Something%", x.Name) > 1).ToList(); 

Но это будет идентично:

ctx.Products.Where(x => x.Name.Contains("Something")).ToList(); 
+0

Привет Мне нужно знать, как построить Выражение (в приведенном выше выражении Body). – sysboard