2015-11-07 5 views
1

Я строй выражения LINQ в C# как это:LINQ выражения добавлять ненужные скобки

public static Expression BuildEqualsExpression(
    ParameterExpression Parameter, 
    PropertyInfo Property, 
    ConstantExpression constant) 
{ 
    Expression propertyExpression = Expression.Property(Parameter, Property); 
    return Expression.Equal(propertyExpression, constant); 
} 

Возвращенного Выражение

(r.Property == constant) 

когда то, что я хочу

r.Property == constant 

без круглых скобок. Мой IQueryProvider не относится к этим двум утверждениям одинаково. Кто-нибудь знает, как я могу избавиться от круглых скобок?

Если I AND два из них вместе, я получаю

((r.Property1 == constant) And (r.Property2 == constant)) 

, когда я хочу

r.Property1 == constant And r.Property2 == constant 

, так как они не являются эквивалентными предикаты.

Редактировать:

Благодарим за помощь. Оказывается, что в SQL сервере 2014, используя следующую команду:

OFFSET 0 ROWS FETCH NEXT 100 ROWS ONLY 

Когда число действительных строк < 100, это заставит запрос выполнить крайне медленно.

+6

Это просто строковое представление выражения, оно не меняет свой смысл. И да, два предиката * * эквивалентны. Ваш IQueryProvider работает над строковым представлением? –

+0

Бэк-магазин моего IQueryProvider не относится к ним одинаково. Мне не нужны круглые скобки.Несмотря на то, что математически они эквивалентны, резервный магазин обрабатывает скобки как конкретную операцию = \ – Magn3s1um

+1

@ Magn3s1um: При всем уважении это не имеет смысла. Какая операция выполняет скобки? –

ответ

4

Не существует узлов выражения LINQ, которые явно представляют круглые скобки. Вместо этого приоритет и ассоциативность операторов автоматически выводятся из структуры дерева выражений.

Похоже, что вы или поставщик запроса вызывают ToString() в выражении. Не делайте этого. В expression trees specification состоянии:

Expression.ToString только для целей отладки легкого веса. [...]

ToString не пытается вернуть семантически точный код C# или VB, в частности. Мы стараемся возвращать краткие строки, свободно предлагая, что узел узла ET [выражение] содержит только для быстрой проверки.

Как отмечает Томас Левеск в комментарии, наилучшим подходом является то, что поставщик запроса напрямую работает с деревьями выражений вместо строк.

Если поставщик запроса принимает только строки, вам придется преобразовать выражение в строку самостоятельно. Ваша задача будет осложнена тем, что дополнительные круглые скобки являются проблематичными, потому что вам все равно нужно вставлять круглые скобки, чтобы различать, скажем, (1 + 2) * 3 от 1 + (2 * 3).

Вот код, чтобы вы начали:

private static readonly Dictionary<ExpressionType, string> s_binaryOperators = 
    new Dictionary<ExpressionType, string> 
    { 
     { ExpressionType.Equal, " == " }, 
     { ExpressionType.And, " AND " }, 
    }; 

public static void ToString(Expression expression, StringBuilder builder) 
{ 
    switch (expression.NodeType) 
    { 
     case ExpressionType.Parameter: 
      builder.Append(((ParameterExpression)expression).Name); 
      break; 

     case ExpressionType.Constant: 
      builder.Append(((ConstantExpression)expression).Value); 
      break; 

     case ExpressionType.MemberAccess: 
      var memberExpression = (MemberExpression)expression; 
      // TODO: Add parentheses if memberExpression.Expression.NodeType 
      // has lower precedence than the current expression. 
      ToString(memberExpression.Expression, builder); 
      builder.Append('.').Append(memberExpression.Member.Name); 
      break; 

     case ExpressionType.Equal: 
     case ExpressionType.And: 
      var binaryExpression = (BinaryExpression)expression; 
      // TODO: Add parentheses if binaryExpression.Left.NodeType 
      // has lower precedence than the current expression. 
      ToString(binaryExpression.Left, builder); 
      builder.Append(s_binaryOperators[expression.NodeType]); 
      // TODO: Add parentheses if binaryExpression.Right.NodeType 
      // has lower precedence than the current expression. 
      ToString(binaryExpression.Right, builder); 
      break; 

     default: 
      throw new NotImplementedException(); 
    } 
} 
+0

Структура Entity помещает круглые скобки вокруг предикатов в предложение where (выражение 1) и (выражение 2). Это сильно замедляет запрос. Любая идея, как предотвратить это? – Magn3s1um

+0

Можете ли вы представить фактический пример SQL-запроса, когда присутствие или отсутствие круглых скобок влияет на план выполнения? Кроме того, какую версию SQL Server вы используете? (Это было бы хорошим кандидатом на новый вопрос, потому что существование такого запроса противоречило бы [этому ответу] (http://stackoverflow.com/a/5525938/1127114).) –

+0

Да, я могу. Легко воспроизводимый. – Magn3s1um