【发布时间】:2011-08-14 11:52:14
【问题描述】:
我有一个让我非常头疼的 Linq 表达式,希望有人能帮我找出我的提供商不喜欢它的原因。
如果我执行以下操作,则效果很好;
Expression<Func<Employee, bool>> expr = e => e.Participant == "Y";
_context.Employees.Where(expr).ToList<IEmployee>();
但是,如果我执行以下操作,我的提供商会不喜欢它。
Expression<Func<IEmployee, bool>> expr = e => e.Participant == "Y";
Expression<Func<Employee, bool>> convertedExpr = ParameterReplacer.Replace
<Func<IEmployee, bool>, Func<Employee, bool>>
(expr,
expr.Parameters.Single(),
Expression.Parameter(typeof(Employee)));
_context.Employees.Where(convertedExpr).ToList<IEmployee>();
我进行转换的原因是我的应用程序的上层只知道接口类型,所以我使用ParameterReplacer(由另一个 SO 成员)。
我比较了有效版本和无效版本之间的 linq 表达式,我能看到的唯一区别是我在 DebugView 属性中看到的参数名称不同。
这是ParameterReplacer的代码;
public static class ParameterReplacer
{
// Produces an expression identical to 'expression'
// except with 'source' parameter replaced with 'target' parameter.
public static Expression<TOutput> Replace<TInput, TOutput>(Expression<TInput> expression, ParameterExpression source, ParameterExpression target)
{
return new ParameterReplacerVisitor<TOutput>(source, target).VisitAndConvert(expression);
}
private class ParameterReplacerVisitor<TOutput> : ExpressionVisitor
{
private ParameterExpression _source;
private ParameterExpression _target;
public ParameterReplacerVisitor(ParameterExpression source, ParameterExpression target)
{
_source = source;
_target = target;
}
internal Expression<TOutput> VisitAndConvert<T>(Expression<T> root)
{
return (Expression<TOutput>)VisitLambda(root);
}
protected override Expression VisitLambda<T>(Expression<T> node)
{
// Leave all parameters alone except the one we want to replace.
var parameters = node.Parameters.Select(p => p == _source ? _target : p);
return Expression.Lambda<TOutput>(Visit(node.Body), parameters);
}
protected override Expression VisitParameter(ParameterExpression node)
{
// Replace the source with the target, visit other params as usual.
return node == _source ? _target : base.VisitParameter(node);
}
}
}
这是 ParameterReplacer 或我的提供程序的问题吗?谁能帮帮我?
我使用的提供者是 Telerik OpenAccess,它抛出的异常是;
InnerException: System.NullReferenceException Message=对象引用未设置为对象的实例。 来源=Telerik.OpenAccess.35.Extensions 堆栈跟踪: 在 Telerik.OpenAccess.Query.ExpressionCompiler.PerformDatabaseQueryImpl(类型 type, Int32 elementAt, Object[] groupResolutionParamValues, Boolean 单,布尔值 checkOid) 在 Telerik.OpenAccess.Query.ExpressionCompiler.PerformDatabaseQuery(类型 type, Int32 elementAt, Object[] groupResolutionParamValues, Boolean 单,布尔值 checkOid) 内部异常:
【问题讨论】:
-
我使用的提供者是 Telerik OpenAccess,它抛出了一个空引用异常。为问题添加了例外。