2011-11-27 10 views
6

式の理解を得ようとしています。私は恐ろしい "パラメータが指定されたLINQ to Entitiesクエリ式にバインドされていませんでした"と打ち明けています。私はSkeetが以前と同様にオンラインでこれに答えるのを見ました。しかし、私は問題を「見る」ことができません。私はColin Meekの例であるhttp://blogs.msdn.com/b/meek/archive/2008/05/02/linq-to-entities-combining-predicates.aspxとMatt WarrenのVisitorExpressionクラスhttp://blogs.msdn.com/b/mattwar/archive/2007/07/31/linq-building-an-iqueryable-provider-part-ii.aspxを使用しています。私はVS 2010、フレームワーク4.0でコンソールアプリケーションを使用しています。それは前に尋ねられて以来、これは死んだ馬を打つことは申し訳ありません。助けてくれてありがとう。恐ろしい "パラメータが指定されたLINQ to Entitiesクエリ式にバインドされていませんでした"例外

徹底するためには、すべてのコードは以下の通りです:ユーティリティで

class Program 
{ 
    static void Main(string[] args) 
    { 
     Expression<Func<Car, bool>> theCarIsRed = c => c.Color == "Red"; 
     Expression<Func<Car, bool>> theCarIsCheap = c => c.Price < 10.0; 
     Expression<Func<Car, bool>> theCarIsRedOrCheap = theCarIsRed.Or(theCarIsCheap); 

     Car one = new Car() { CarId = 1, Color = "Red", Price = 10.0 }; 
     Car two = new Car() { CarId = 2, Color = "Blue", Price = 9.0 }; 
     Car three = new Car() { CarId = 3, Color = "Black", Price = 5.0 }; 
     Car four = new Car() { CarId = 4, Color = "Red", Price = 5.0 }; 

     EntityDBContext context = new EntityDBContext(); 
     context.CarEntity.Add(one); 
     context.CarEntity.Add(two); 
     context.CarEntity.Add(three); 
     context.CarEntity.Add(four); 

     using (var db = context) 
     { 
      // Bang 
      var query = db.CarEntity.AsQueryable().Where(theCarIsRedOrCheap).ToList(); 

      foreach (var item in query) 
      { 
       Console.WriteLine(item.Color, item.Price); 
      } 
     } 

     Console.ReadKey(); 
    } 
} 

public class Car 
{ 
    [Key] 
    public int CarId { get; set; } 
    public string Color { get; set; } 
    public double Price { get; set; } 
} 


public static class Utility 
{ 
    public static Expression<T> Compose<T>(this Expression<T> first, 
     Expression<T> second, Func<Expression, Expression, Expression> merge) 
    { 
     var map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f); 

     var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body); 

     return Expression.Lambda<T>(merge(first.Body, second.Body), first.Parameters); 
    } 

    public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second) 
    { 
     return first.Compose(second, Expression.And); 
    } 

    public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second) 
    { 
     return first.Compose(second, Expression.Or); 
    } 
} 


public class ParameterRebinder : ExpressionVisitor 
{ 
    private readonly Dictionary<ParameterExpression, ParameterExpression> map; 

    public ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map) 
    { 
     this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>(); 
    } 

    public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp) 
    { 
     return new ParameterRebinder(map).Visit(exp); 
    } 

    protected override Expression VisitParameter(ParameterExpression parmEx) 
    { 
     ParameterExpression replacement; 
     if (map.TryGetValue(parmEx, out replacement)) 
     { 
      parmEx = replacement; 
     } 

     return base.VisitParameter(parmEx); 
    } 
} 

public abstract class ExpressionVisitor 
{ 
    protected ExpressionVisitor() 
    { 
    } 

    protected virtual Expression Visit(Expression exp) 
    { 
     if (exp == null) 
     { 
      return exp; 
     } 

     switch (exp.NodeType) 
     { 
      case ExpressionType.Negate: 
      case ExpressionType.NegateChecked: 
      case ExpressionType.Not: 
      case ExpressionType.Convert: 
      case ExpressionType.ConvertChecked: 
      case ExpressionType.ArrayLength: 
      case ExpressionType.Quote: 
      case ExpressionType.TypeAs: 
       return this.VisitUnary((UnaryExpression) exp); 
      case ExpressionType.Add: 
      case ExpressionType.AddChecked: 
      case ExpressionType.Subtract: 
      case ExpressionType.SubtractChecked: 
      case ExpressionType.Multiply: 
      case ExpressionType.MultiplyChecked: 
      case ExpressionType.Divide: 
      case ExpressionType.Modulo: 
      case ExpressionType.And: 
      case ExpressionType.AndAlso: 
      case ExpressionType.Or: 
      case ExpressionType.OrElse: 
      case ExpressionType.LessThan: 
      case ExpressionType.LessThanOrEqual: 
      case ExpressionType.GreaterThan: 
      case ExpressionType.GreaterThanOrEqual: 
      case ExpressionType.Equal: 
      case ExpressionType.NotEqual: 
      case ExpressionType.Coalesce: 
      case ExpressionType.ArrayIndex: 
      case ExpressionType.RightShift: 
      case ExpressionType.LeftShift: 
      case ExpressionType.ExclusiveOr: 
       return this.VisitBinary((BinaryExpression) exp); 
      case ExpressionType.TypeIs: 
       return this.VisitTypeIs((TypeBinaryExpression) exp); 
      case ExpressionType.Conditional: 
       return this.VisitConditional((ConditionalExpression) exp); 
      case ExpressionType.Constant: 
       return this.VisitConstant((ConstantExpression) exp); 
      case ExpressionType.Parameter: 
       return this.VisitParameter((ParameterExpression) exp); 
      case ExpressionType.MemberAccess: 
       return this.VisitMemberAccess((MemberExpression) exp); 
      case ExpressionType.Call: 
       return this.VisitMethodCall((MethodCallExpression) exp); 
      case ExpressionType.Lambda: 
       return this.VisitLambda((LambdaExpression) exp); 
      case ExpressionType.New: 
       return this.VisitNew((NewExpression) exp); 
      case ExpressionType.NewArrayInit: 
      case ExpressionType.NewArrayBounds: 
       return this.VisitNewArray((NewArrayExpression) exp); 
      case ExpressionType.Invoke: 
       return this.VisitInvocation((InvocationExpression) exp); 
      case ExpressionType.MemberInit: 
       return this.VisitMemberInit((MemberInitExpression) exp); 
      case ExpressionType.ListInit: 
       return this.VisitListInit((ListInitExpression) exp); 
      default: 
       throw new Exception(String.Format("Unhandled expression type: '{0}'", exp.NodeType)); 

     } 
    } 

    protected virtual MemberBinding VisitBinding(MemberBinding binding) 
    { 
     switch (binding.BindingType) 
     { 
      case MemberBindingType.Assignment: 
       return this.VisitMemberAssignment((MemberAssignment) binding); 
       case MemberBindingType.MemberBinding: 
       return this.VisitMemberMemberBinding((MemberMemberBinding) binding); 
       case MemberBindingType.ListBinding: 
       return this.VisitMemberListBinding((MemberListBinding) binding); 
      default: 
       throw new Exception(String.Format("Unhandled binding type '{0}'", binding.BindingType)); 
     } 
    } 

    protected virtual Expression VisitListInit(ListInitExpression init) 
    { 
     NewExpression n = this.VisitNew(init.NewExpression); 
     IEnumerable<ElementInit> initializers = this.VisitElementInitializerList(init.Initializers); 

     if (n != init.NewExpression || initializers != init.Initializers) 
     { 
      return Expression.ListInit(n, initializers); 
     } 

     return init; 
    } 

    protected virtual Expression VisitMemberInit(MemberInitExpression memberInitExpression) 
    { 
     NewExpression n = this.VisitNew(memberInitExpression.NewExpression); 
     IEnumerable<MemberBinding> bindings = this.VisitBindingList(memberInitExpression.Bindings); 

     if (n != memberInitExpression.NewExpression || bindings != memberInitExpression.Bindings) 
     { 
      return Expression.MemberInit(n, bindings); 
     } 

     return memberInitExpression; 
    } 

    protected virtual Expression VisitInvocation(InvocationExpression invocationExpression) 
    { 
     IEnumerable<Expression> args = this.VisitExpressionList(invocationExpression.Arguments); 
     Expression expr = this.Visit(invocationExpression.Expression); 

     if (args != invocationExpression.Arguments || expr != invocationExpression.Expression) 
     { 
      return Expression.Invoke(expr, args); 
     } 

     return invocationExpression; 
    } 

    protected virtual Expression VisitNewArray(NewArrayExpression newArrayExpression) 
    { 
     IEnumerable<Expression> exprs = this.VisitExpressionList(newArrayExpression.Expressions); 

     if (exprs != newArrayExpression.Expressions) 
     { 
      if (newArrayExpression.NodeType == ExpressionType.NewArrayInit) 
      { 
       return Expression.NewArrayInit(newArrayExpression.Type.GetElementType(), exprs); 
      } 
      else 
      { 
       return Expression.NewArrayBounds(newArrayExpression.Type.GetElementType()); 
      } 
     } 

     return newArrayExpression; 
    } 

    protected virtual NewExpression VisitNew(NewExpression newExpression) 
    { 
     IEnumerable<Expression> args = this.VisitExpressionList(newExpression.Arguments); 

     if (args != newExpression.Arguments) 
     { 
      if (newExpression.Members != null) 
      { 
       return Expression.New(newExpression.Constructor, args, newExpression.Members); 
      } 
      else 
      { 
       return Expression.New(newExpression.Constructor, args); 
      } 
     } 

     return newExpression; 
    } 

    protected virtual Expression VisitLambda(LambdaExpression lambdaExpression) 
    { 
     Expression body = this.Visit(lambdaExpression.Body); 
     if (body != lambdaExpression.Body) 
     { 
      return Expression.Lambda(lambdaExpression.Type, body, lambdaExpression.Parameters); 
     } 

     return lambdaExpression; 
    } 

    protected virtual Expression VisitMethodCall(MethodCallExpression methodCallExpression) 
    { 
     Expression obj = this.Visit(methodCallExpression.Object); 
     IEnumerable<Expression> args = this.VisitExpressionList(methodCallExpression.Arguments); 

     if (obj != methodCallExpression.Object || args != methodCallExpression.Arguments) 
     { 
      return Expression.Call(obj, methodCallExpression.Method, args); 
     } 

     return methodCallExpression; 
    } 

    protected virtual Expression VisitMemberAccess(MemberExpression memberExpression) 
    { 
     Expression exp = this.Visit(memberExpression.Expression); 

     if (exp != memberExpression.Expression) 
     { 
      return Expression.MakeMemberAccess(exp, memberExpression.Member); 
     } 

     return memberExpression; 
    } 

    protected virtual Expression VisitParameter(ParameterExpression parameterExpression) 
    { 
     return parameterExpression; 
    } 

    protected virtual Expression VisitConstant(ConstantExpression constantExpression) 
    { 
     return constantExpression; 
    } 

    protected virtual Expression VisitConditional(ConditionalExpression conditionalExpression) 
    { 
     Expression test = this.Visit(conditionalExpression.Test); 
     Expression ifTrue = this.Visit(conditionalExpression.IfTrue); 
     Expression ifFalse = this.Visit(conditionalExpression.IfFalse); 

     if (test != conditionalExpression.Test || ifTrue != conditionalExpression.IfTrue || ifFalse != conditionalExpression.IfFalse) 
     { 
      return Expression.Condition(test, ifTrue, ifFalse); 
     } 

     return conditionalExpression; 
    } 

    protected virtual Expression VisitTypeIs(TypeBinaryExpression typeBinaryExpression) 
    { 
     Expression expr = this.Visit(typeBinaryExpression.Expression); 
     if (expr != typeBinaryExpression) 
     { 
      return Expression.TypeIs(expr, typeBinaryExpression.TypeOperand); 
     } 

     return typeBinaryExpression; 
    } 

    protected virtual Expression VisitBinary(BinaryExpression binaryExpression) 
    { 
     Expression left = this.Visit(binaryExpression.Left); 
     Expression right = this.Visit(binaryExpression.Right); 
     Expression conversion = this.Visit(binaryExpression.Conversion); 

     if (left != binaryExpression.Left || right != binaryExpression.Right || conversion != binaryExpression.Conversion) 
     { 
      if (binaryExpression.NodeType == ExpressionType.Coalesce && binaryExpression.Conversion != null) 
      { 
       return Expression.Coalesce(left, right, conversion as LambdaExpression); 
      } 
      else 
      { 
       return Expression.MakeBinary(binaryExpression.NodeType, left, right, binaryExpression.IsLiftedToNull, 
              binaryExpression.Method); 
      } 
     } 

     return binaryExpression; 
    } 

    protected virtual Expression VisitUnary(UnaryExpression unaryExpression) 
    { 
     Expression operand = this.Visit(unaryExpression.Operand); 
     if (operand != unaryExpression.Operand) 
     { 
      return Expression.MakeUnary(unaryExpression.NodeType, operand, unaryExpression.Type, 
             unaryExpression.Method); 
     } 

     return unaryExpression; 
    } 

    protected virtual ReadOnlyCollection<Expression> VisitExpressionList(ReadOnlyCollection<Expression> original) 
    { 
     List<Expression> list = null; 

     for (int i = 0, n = original.Count; i < n; i++) 
     { 
      Expression p = this.Visit(original[i]); 
      if (list != null) 
      { 
       list.Add(p); 
      } 
      else if (p != original[i]) 
      { 
       list = new List<Expression>(n); 
       for (int j = 0; j < i; j++) 
       { 
        list.Add(original[j]); 
       } 

       list.Add(p); 
      } 
     } 

     return list != null ? list.AsReadOnly() : original; 
    } 

    protected virtual IEnumerable<MemberBinding> VisitBindingList(ReadOnlyCollection<MemberBinding> original) 
    { 
     List<MemberBinding> list = null; 

     for (int i = 0, n = original.Count; i < n; i++) 
     { 
      MemberBinding b = this.VisitBinding(original[i]); 

      if (list != null) 
      { 
       list.Add(b); 
      } 
      else if (b != original[i]) 
      { 
       list = new List<MemberBinding>(n); 

       for (int j = 0; j < i; j++) 
       { 
        list.Add(original[j]); 
       } 

       list.Add(b); 
      } 
     } 

     if (list != null) 
     { 
      return list; 
     } 

     return original; 
    } 

    protected virtual MemberAssignment VisitMemberAssignment(MemberAssignment assignment) 
    { 
     Expression e = this.Visit(assignment.Expression); 

     if (e != assignment.Expression) 
     { 
      return Expression.Bind(assignment.Member, e); 
     } 

     return assignment; 
    } 

    protected virtual MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding binding) 
    { 
     IEnumerable<MemberBinding> bindings = this.VisitBindingList(binding.Bindings); 

     if (bindings != binding.Bindings) 
     { 
      return Expression.MemberBind(binding.Member, bindings); 
     } 

     return binding; 
    } 

    protected virtual MemberListBinding VisitMemberListBinding(MemberListBinding binding) 
    { 
     IEnumerable<ElementInit> initializers = this.VisitElementInitializerList(binding.Initializers); 

     if (initializers != binding.Initializers) 
     { 
      return Expression.ListBind(binding.Member, initializers); 
     } 

     return binding; 
    } 

    protected virtual IEnumerable<ElementInit> VisitElementInitializerList(ReadOnlyCollection<ElementInit> original) 
    { 
     List<ElementInit> list = null; 

     for (int i = 0, n = original.Count; i < n; i++) 
     { 
      ElementInit init = this.VisitElementInitializer(original[i]); 

      if (list != null) 
      { 
       list.Add(init); 
      } 
      else if (init != original[i]) 
      { 
       list = new List<ElementInit>(n); 

       for (int j = 0; j < i; j++) 
       { 
        list.Add(original[j]); 
       } 

       list.Add(init); 
      } 
     } 

     if (list != null) 
     { 
      return list; 
     } 

     return original; 
    } 

    protected virtual ElementInit VisitElementInitializer(ElementInit initializer) 
    { 
     ReadOnlyCollection<Expression> arguments = this.VisitExpressionList(initializer.Arguments); 

     if (arguments != initializer.Arguments) 
     { 
      return Expression.ElementInit(initializer.AddMethod, arguments); 
     } 

     return initializer; 
    } 
} 

答えて

0

は、以下にコン方法を交換してください。

{ 
    var map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f); 

    var secondRebound = ParameterRebinder.ReplaceParameters(map, second); 

    return Expression.Lambda<T>(merge(first.Body, secondRebound.Body), first.Parameters); 
} 
関連する問題