У меня есть выражение 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 = Ссылка на объект не установлена наэкземпляр объекта.Source = Telerik.Тип type, Int32 elementAt, Object [] groupResolutionParamValues, логический одиночный, логический checkOid) InnerException: