1 //---------------------------------------------------------------------
2 // <copyright file="BindingContext.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
7 //---------------------------------------------------------------------
9 using CqtExpression = System.Data.Common.CommandTrees.DbExpression;
10 using LinqExpression = System.Linq.Expressions.Expression;
11 using System.Linq.Expressions;
12 using System.Collections.ObjectModel;
14 using System.Collections.Generic;
15 using System.Data.Common.CommandTrees;
16 using System.Data.Metadata.Edm;
17 using System.Reflection;
18 using System.Data.Common.EntitySql;
19 using System.Diagnostics;
20 using System.Data.Common;
21 using System.Globalization;
22 namespace System.Data.Objects.ELinq
25 /// Class containing binding information for an expression converter (associating CQT bindings
26 /// with LINQ lambda parameter or LINQ sub-expressions)
31 /// BindingContext context = ...;
33 /// // translate a "Where" lamba expression input.Where(i => i.X > 2);
34 /// LambdaExpression whereLambda = ...;
35 /// CqtExpression inputCqt = Translate(whereLambda.Arguments[1]);
36 /// CqtExpression inputBinding = CreateExpressionBinding(inputCqt).Var;
38 /// // push the scope defined by the parameter
39 /// context.PushBindingScope(new KeyValuePair{ParameterExpression, CqtExpression}(whereLambda.Parameters[0], inputBinding));
41 /// // translate the expression in this context
42 /// CqtExpression result = Translate(whereLambda.Expression);
45 /// context.PopBindingScope();
48 internal sealed class BindingContext
50 private readonly Stack<Binding> _scopes;
53 /// Initialize a new binding context
55 internal BindingContext()
57 _scopes = new Stack<Binding>();
61 /// Set up a new binding scope where parameter expressions map to their paired CQT expressions.
63 /// <param name="binding">DbExpression/LinqExpression binding</param>
64 internal void PushBindingScope(Binding binding)
66 _scopes.Push(binding);
70 /// Removes a scope when leaving a particular sub-expression.
72 /// <returns>Scope.</returns>
73 internal void PopBindingScope()
78 internal bool TryGetBoundExpression(Expression linqExpression, out CqtExpression cqtExpression)
80 cqtExpression = _scopes
81 .Where(binding => binding.LinqExpression == linqExpression)
82 .Select(binding => binding.CqtExpression)
84 return cqtExpression != null;
89 /// Class describing a LINQ parameter and its bound expression. For instance, in
91 /// products.Select(p => p.ID)
93 /// the 'products' query is the bound expression, and 'p' is the parameter.
95 internal sealed class Binding
97 internal Binding(Expression linqExpression, CqtExpression cqtExpression)
99 EntityUtil.CheckArgumentNull(linqExpression, "linqExpression");
100 EntityUtil.CheckArgumentNull(cqtExpression, "cqtExpression");
101 LinqExpression = linqExpression;
102 CqtExpression = cqtExpression;
105 internal readonly Expression LinqExpression;
106 internal readonly CqtExpression CqtExpression;