LINQ表达式问题

时间:2011-08-14 11:52:14

标签: .net linq lambda

我有一个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在下层使用具体类型的Expression(由另一个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   single,Boolean checkOid)               在   Telerik.OpenAccess.Query.ExpressionCompiler.PerformDatabaseQuery(类型   type,Int32 elementAt,Object [] groupResolutionParamValues,Boolean   single,Boolean checkOid)          的InnerException:

1 个答案:

答案 0 :(得分:1)

我从未使用过您的提供商,所以我无法确定,但考虑到情况,我认为这是个不错的选择:

因为,唯一的区别是第二个表达式中的参数为null Name,并且您获得的异常是一个空引用异常,我认为这正是问题所在。尝试将Name更改为非空值。

这意味着将新参数的创建更改为:

Expression.Parameter(typeof(Employee), "e")