我正在用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,这将导致查询执行速度非常慢。
答案 0 :(得分: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();
}
}