2011-08-14 3 views
1

나는 진짜 두통을 줄 수있는 Linq 표현식을 가지고 있으며, 왜 내 공급자가 왜 그것을 좋아하지 않는지 알 수 있도록 도와 줄 수 있기를 바랍니다.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 메시지 = 개체 참조가 개체의 인스턴스로 설정되지 않았습니다. 자료 = Telerik.OpenAccess.35.Extensions 스택 트레이스 : Telerik.OpenAccess.Query.ExpressionCompiler.PerformDatabaseQueryImpl에서 (타입 유형 INT32 elementAt이 Object [] groupResolutionParamValues ​​단일 불리언 부울 checkOid) Telerik 에서 . OpenAccess.Query.ExpressionCompiler.PerformDatabaseQuery 의 InnerException (유형 유형은 INT32 elementAt는 [] groupResolutionParamValues, 부울 하나, 부울 checkOid 객체) : 나는 당신의 공급자를 사용한 적이

+0

무슨 에러가 발생합니까? – svick

+0

내가 사용중인 공급자가 Telerik OpenAccess이고 null 참조 예외가 발생했습니다. 질문에 예외를 추가했습니다. – David

답변

1

을, 그래서 나는 확신 할 수 없다 , 그러나 상황을 고려할 때, 나는 이것이 좋은 내기라고 생각합니다 :

유일한 차이점은 두 번째 표현식의 매개 변수가 null Name이고 예외가 null 참조 예외이므로, 나는 이것이 정확히 문제라고 생각합니다. Name을 null이 아닌 값으로 변경해보십시오.

그 같은 새 매개 변수의 생성을 변경하는 의미

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

우수! 그것은 정확히 문제였습니다. 마침내 나는 계속 나아갈 수 있습니다. – David