1

I have a Linq Expression that is giving me a real headache and hope someone can help me find out why my provider does not like it.

If I do the following it works fine;

Expression<Func<Employee, bool>> expr = e => e.Participant == "Y";
_context.Employees.Where(expr).ToList<IEmployee>();

However, if I do the following my provider doesn't like it.

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>();

The reason I am doing the conversion is that the upper layer of my application only knows about the interface type, so I convert it to a Expression that uses the concrete type in the lower layer using the ParameterReplacer (kindly supplied by another SO member).

I have compared the linq expressions between the version that works and the one that doesn't and the only difference I can see is in what I see in the DebugView property in that the parameter names are different.

Here is the code for the 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);
 }
 } 
}

Is this an issue with the ParameterReplacer or my provider? Can any one help me out?

The provider I am using is Telerik OpenAccess and the exception its throwing is;

InnerException: System.NullReferenceException Message=Object reference not set to an instance of an object. Source=Telerik.OpenAccess.35.Extensions StackTrace: at Telerik.OpenAccess.Query.ExpressionCompiler.PerformDatabaseQueryImpl(Type type, Int32 elementAt, Object[] groupResolutionParamValues, Boolean single, Boolean checkOid) at Telerik.OpenAccess.Query.ExpressionCompiler.PerformDatabaseQuery(Type type, Int32 elementAt, Object[] groupResolutionParamValues, Boolean single, Boolean checkOid) InnerException:

asked Aug 14, 2011 at 11:52
1
  • The provider I am using is Telerik OpenAccess and its throwing a null reference exception. Added exception to question. Commented Aug 14, 2011 at 12:40

1 Answer 1

1

I have never used your provider, so I can't be sure, but considering the circumstances, I think this is good bet:

Since, the only difference is that the parameter in the second expression has null Name and the exception you are getting is a null reference exception, I think that's exactly the problem. Try changing the Name to something non-null.

That means changing the creation of the new parameter to something like:

Expression.Parameter(typeof(Employee), "e")
answered Aug 14, 2011 at 12:47
Sign up to request clarification or add additional context in comments.

1 Comment

Excellent! That was exactly the problem. At last, I can move on.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.