我正在用 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 Server 2014 中,使用此命令:
OFFSET 0 ROWS FETCH NEXT 100 ROWS ONLY
当实际行数<100时,这会导致查询执行的非常慢。
最佳答案
没有显式表示括号的 LINQ 表达式节点。相反,运算符优先级和结合性是从表达式树的结构中自动推断出来的。
您或查询提供者似乎正在对表达式调用 ToString()。 不要这样做。 expression trees specification状态:
Expression.ToString is for light weight debugging purposes only. [...]
ToString does not try to return semantically accurate C# or VB code in particular. We try to return terse strings loosely suggesting what an ET [expression tree] node contains for quick inspection only.
正如 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();
}
}
关于c# - LINQ 表达式添加不必要的括号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33584994/