2015-11-07 78 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並沒有平等對待這兩個陳述。有誰知道我如何擺脫括號?

如果我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 [表達式樹]節點包含的內容僅供快速檢查。

正如Thomas Levesque在評論中指出的,最好的方法是讓查詢提供者直接使用表達式樹而不是字符串。

如果查詢提供程序只接受字符串,則必須自己將表達式轉換爲字符串。您的任務會因爲額外的括號存在問題而變得複雜,因爲您仍然需要插入括號來區分(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

實體框架確實在where子句(表達式1)和(表達式2)中的謂詞周圍放置了括號。這極大地降低了查詢速度。任何想法如何防止這一點? – Magn3s1um

+0

您是否可以提供一個SQL查詢的實際示例,其中括號的存在或不存在會影響執行計劃?另外,你使用的是什麼版本的SQL Server? (這將是一個新問題的好候選者,因爲這樣的查詢的存在會與[此答案]相矛盾(http://stackoverflow.com/a/5525938/1127114)。) –

+0

是的,我可以。容易重現。 – Magn3s1um