ExpressionCopier.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataEntity / System / Data / Common / CommandTrees / Internal / ExpressionCopier.cs / 4 / ExpressionCopier.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....], [....]
//--------------------------------------------------------------------- 
 
using System;
using System.Collections.Generic; 
using System.Diagnostics;
using System.Globalization;

using System.Data.Common; 
using System.Data.Metadata.Edm;
using System.Data.Common.CommandTrees; 
 
namespace System.Data.Common.CommandTrees.Internal
{ 
    /// 
    /// Clones an expression tree
    /// 
    internal class ExpressionCopier : DbExpressionVisitor 
    {
        ///  
        /// The MetadataMapper class is a helper class that logically translates 
        /// metadata constructs from one space to another. The objects that are translated
        /// include 
        ///   Types
        ///   Properties
        ///   Methods
        ///   Functions 
        ///   Extents
        ///   EntitySets 
        /// The default implementation is to simply return the specified metadata instance 
        /// (an 'identity' mapping)
        ///  
        protected class MetadataMapper
        {
            internal static readonly MetadataMapper IdentityMapper = new MetadataMapper();
 
            internal MetadataMapper() {}
 
            internal virtual EdmType                Map(EdmType s) { return s; } 
            internal virtual EntitySetBase          Map(EntitySetBase e) { return e; }
            internal virtual EntitySet              Map(EntitySet e) { return e; } 
            internal virtual EdmFunction            Map(EdmFunction f) { return f; }
            internal virtual NavigationProperty     Map(NavigationProperty p) { return p; }
            internal virtual EdmProperty            Map(EdmProperty p) { return p; }
            internal virtual RelationshipEndMember  Map(RelationshipEndMember m) { return m; } 
            internal virtual TypeUsage              Map(TypeUsage t) { return t; }
 
#if METHOD_EXPRESSION 
            internal virtual MethodMetadata    Map(MethodMetadata m) { return m; }
#endif 

        }

        private class WorkspaceMapper : MetadataMapper 
        {
            private MetadataWorkspace _metadata; 
            private Dictionary _transientTypes = new Dictionary(); 

            internal WorkspaceMapper(MetadataWorkspace destinationWorkspace) 
                : base()
            {
                _metadata = destinationWorkspace;
            } 

            #region MetadataMapper Overrides 
 
            internal override EdmType Map(EdmType type)
            { 
                EdmType retType = null;

                if (BuiltInTypeKind.RefType == type.BuiltInTypeKind)
                { 
                    RefType refType = (RefType)type;
                    retType = new RefType((EntityType)Map(refType.ElementType)); 
                } 
                else if (BuiltInTypeKind.CollectionType == type.BuiltInTypeKind)
                { 
                    CollectionType collectionType = (CollectionType)type;
                    retType = new CollectionType(Map(collectionType.TypeUsage));
                }
                else if (BuiltInTypeKind.RowType == type.BuiltInTypeKind) 
                {
                    RowType rowType = (RowType)type; 
                    List columns = new List(); 
                    foreach (EdmProperty p in rowType.Properties)
                    { 
                        columns.Add(new EdmProperty(p.Name, Map(p.TypeUsage)));
                    }

                    RowType newRowType = new RowType(columns, rowType.InitializerMetadata); 
                    retType = newRowType;
                } 
                else 
                {
                    if (!_metadata.TryGetType(type.Name, type.NamespaceName, type.DataSpace, out retType) || 
                        null == retType)
                    {

                        throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_TypeNotFound(TypeHelpers.GetFullName(type))); 
                    }
                } 
 
                return retType;
            } 

            internal override EntitySetBase Map(EntitySetBase e)
            {
                EntityContainer container; 
                if (_metadata.TryGetEntityContainer(e.EntityContainer.Name, e.EntityContainer.DataSpace, out container))
                { 
                    EntitySetBase extent = null; 
                    if (container.BaseEntitySets.TryGetValue(e.Name, false, out extent) &&
                        extent != null) 
                    {
                        return extent;
                    }
 
                    throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EntitySetNotFound(e.EntityContainer.Name, e.Name));
                } 
 
                throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EntityContainerNotFound(e.EntityContainer.Name));
            } 

            internal override EntitySet Map(EntitySet e)
            {
                EntityContainer container; 
                if(_metadata.TryGetEntityContainer(e.EntityContainer.Name, e.EntityContainer.DataSpace, out container))
                { 
                    EntitySetBase set = null; 
                    if (container.BaseEntitySets.TryGetValue(e.Name, false, out set))
                    { 
                        EntitySet entitySet = set as EntitySet;
                        if (entitySet != null)
                        {
                            return entitySet; 
                        }
                    } 
 
                    throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EntitySetNotFound(e.EntityContainer.Name, e.Name));
                } 

                throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EntityContainerNotFound(e.EntityContainer.Name));
            }
 
            internal override EdmFunction Map(EdmFunction f)
            { 
                TypeUsage[] paramTypes = new TypeUsage[f.Parameters.Count]; 
                int idx = 0;
                foreach (FunctionParameter p in f.Parameters) 
                {
                    paramTypes[idx] = Map(p.TypeUsage);
                    idx++;
                } 

                EdmFunction retFunc = null; 
                if( _metadata.TryGetFunction(f.Name, f.NamespaceName, paramTypes, false, f.DataSpace, out retFunc) && 
                    retFunc != null)
                { 
                    return retFunc;
                }

                throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_FunctionNotFound(TypeHelpers.GetFullName(f))); 
            }
 
            internal override NavigationProperty Map(NavigationProperty prop) 
            {
                NavigationProperty retProp; 
                if (!TryMapMember(prop, out retProp))
                {
                    throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_PropertyNotFound(prop.Name, TypeHelpers.GetFullName(prop.DeclaringType)));
                } 
                return retProp;
            } 
 
            internal override EdmProperty Map(EdmProperty prop)
            { 
                EdmProperty retProp;
                if (!TryMapMember(prop, out retProp))
                {
                    throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_PropertyNotFound(prop.Name, TypeHelpers.GetFullName(prop.DeclaringType))); 
                }
                return retProp; 
            } 

            internal override RelationshipEndMember Map(RelationshipEndMember end) 
            {
                RelationshipEndMember retEnd;
                if (!TryMapMember(end, out retEnd))
                { 
                    throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EndNotFound(end.Name, TypeHelpers.GetFullName(end.DeclaringType)));
                } 
 
                return retEnd;
            } 

            private bool TryMapMember(TMemberType prop, out TMemberType foundProp) where TMemberType : EdmMember
            {
                foundProp = null; 
                StructuralType mappedType = Map(prop.DeclaringType) as StructuralType;
                if (mappedType != null) 
                { 
                    EdmMember foundMember = null;
                    if (mappedType.Members.TryGetValue(prop.Name, false, out foundMember)) 
                    {
                        foundProp = foundMember as TMemberType;
                    }
                } 

                return (foundProp != null); 
            } 

#if METHOD_EXPRESSION 
            internal override MethodMetadata Map(MethodMetadata meth)
            {
                MethodMetadata retMethod = null;
 
                List mappedParamTypes = new List();
                foreach (IParameterMetadata methParam in meth.Parameters) 
                { 
                    mappedParamTypes.Add(this.Map(methParam.Type));
                } 

                TypeMetadata mappedType = this.Map(meth.DefiningType);
                foreach (MemberMetadata member in mappedType.GetMemberByName(meth.Name))
                { 
                    // Ignore the member if:
                    // - It's not a method, OR 
                    // - It's IsStatic property doesn't match, OR 
                    // - It doesn't declare the right number of parameters.
                    MethodMetadata mappedMeth = member as MethodMetadata; 
                    if( null == mappedMeth ||
                        mappedMeth.IsStatic != meth.IsStatic ||
                        mappedMeth.Parameters.Count != mappedParamTypes.Count)
                    { 
                        continue;
                    } 
 
                    // Assume that the method matches, which is correct for the case
                    // where the required method and this method both declare no parameters. 
                    bool paramMatch = true;
                    for (int idx = 0; idx < mappedParamTypes.Count; idx++)
                    {
                        // If the type of any parameter to the method under consideration 
                        // does not match the type of the corresponding parameter from the
                        // source method, then this cannot be the correct destination method. 
                        if (!mappedParamTypes[idx].Equals(mappedMeth.Parameters[idx].Type)) 
                        {
                            paramMatch = false; 
                            break;
                        }
                    }
 
                    // If any of the parameter types didn't match then move on.
                    if (!paramMatch) 
                    { 
                        continue;
                    } 

                    // This is the required method.
                    retMethod = mappedMeth;
                    break; 
                }
 
                if (null == retMethod) 
                {
                    throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_MethodNotFound(meth.Name, mappedType.FullName)); 
                }

                return retMethod;
            } 
#endif
 
            internal override TypeUsage Map(TypeUsage type) 
            {
                // 
                // If the target metatadata workspace contains the same type instances, then the type does not
                // need to be 'mapped' and the same TypeUsage instance may be returned. This can happen if the
                // target workspace and the workspace of the source Command Tree are using the same ItemCollection.
                // 
                EdmType retEdmType = Map(type.EdmType);
                if (object.ReferenceEquals(retEdmType, type.EdmType)) 
                { 
                    return type;
                } 

                //
                // Retrieve the Facets from this type usage so that
                // 1) They can be used to map the type if it is a primitive type 
                // 2) They can be applied to the new type usage that references the mapped type
                // 
                Facet[] facets = new Facet[type.Facets.Count]; 
                int idx = 0;
                foreach (Facet f in type.Facets) 
                {
                    facets[idx] = f;
                    idx++;
                } 

                return TypeUsage.Create(retEdmType, facets); 
            } 
            #endregion
        } 

        private MetadataMapper _mapper;
        private DbCommandTree _commandTree;
 
        protected DbCommandTree CommandTree
        { 
            get { return this._commandTree; } 
        }
 
        protected ExpressionCopier(DbCommandTree commandTree, MetadataMapper mapper)
        {
            _commandTree = commandTree;
            _mapper = mapper; 
        }
 
        private static MetadataMapper GetMapper(MetadataWorkspace source, MetadataWorkspace destination) 
        {
            ItemCollection mappingItemCollection = source.GetItemCollection(DataSpace.CSSpace); 
            ItemCollection destinationMappingItemCollection = destination.GetItemCollection(DataSpace.CSSpace);

            if (!object.ReferenceEquals(mappingItemCollection, destinationMappingItemCollection))
            { 
                EntityBid.Trace(" Using cross-workspace metadata mapper\n");
                return new WorkspaceMapper(destination); 
            } 

            EntityBid.Trace(" Using identity metadata mapper\n"); 
            return MetadataMapper.IdentityMapper;
        }

        internal static DbExpression Copy(DbCommandTree destination, DbExpression expression) 
        {
            Debug.Assert(destination != null, "Destination Command Tree is null"); 
            Debug.Assert(expression != null, "DbExpression is null"); 

            using(new EntityBid.ScopeAuto(" destination=%d#", destination.ObjectId)) 
            {
                EntityBid.Trace(" expression=%d#, %d{cqt.DbExpressionKind}\n", DbExpression.GetObjectId(expression), DbExpression.GetExpressionKind(expression));

                ExpressionCopier copier = new ExpressionCopier(destination, GetMapper(expression.CommandTree.MetadataWorkspace, destination.MetadataWorkspace)); 
                return copier.VisitExpr(expression);
            } 
        } 

        public List VisitList(IList exprList) where T: DbExpression 
        {
            List retList = null;
            if (exprList != null)
            { 
                retList = new List();
                for (int idx = 0; idx < exprList.Count; idx++) 
                { 
                    retList.Add((T)this.VisitExpr(exprList[idx]));
                } 
            }

            return retList;
        } 
        public List VisitExprList(IList exprList)
        { 
            return VisitList(exprList); 
        }
 
        public DbExpressionBinding VisitBinding(DbExpressionBinding b)
        {
            DbExpression newExpr = VisitExpr(b.Expression);
            return this._commandTree.CreateExpressionBinding(newExpr, b.VariableName); 
        }
 
        public DbGroupExpressionBinding VisitGroupExpressionBinding(DbGroupExpressionBinding gb) 
        {
            DbExpression newExpr = VisitExpr(gb.Expression); 
            return this._commandTree.CreateGroupExpressionBinding(newExpr, gb.VariableName, gb.GroupVariableName);
        }

        public List VisitBindingList(IList bindingList) 
        {
            List retList = null; 
            if (bindingList != null) 
            {
                retList = new List(); 
                for (int idx = 0; idx < bindingList.Count; idx++)
                {
                    retList.Add(this.VisitBinding(bindingList[idx]));
                } 
            }
 
            return retList; 
        }
 
        public List VisitSortOrder(IList sortOrder)
        {
            List skeys = new List();
            for(int idx = 0; idx < sortOrder.Count; idx++) 
            {
                DbSortClause s = sortOrder[idx]; 
                DbExpression keyExpr = VisitExpr(s.Expression); 
                bool asc = s.Ascending;
                if(!string.IsNullOrEmpty(s.Collation)) 
                {
                    skeys.Add(_commandTree.CreateSortClause(keyExpr, asc, s.Collation));
                }
                else 
                {
                    skeys.Add(_commandTree.CreateSortClause(keyExpr, asc)); 
                } 
            }
 
            return skeys;
        }

        public virtual DbFunctionAggregate VisitFunctionAggregate(DbFunctionAggregate a) 
        {
            if (a.Distinct) 
            { 
                return _commandTree.CreateDistinctFunctionAggregate(_mapper.Map(a.Function), VisitExpr(a.Arguments[0]));
            } 
            else
            {
                return _commandTree.CreateFunctionAggregate(_mapper.Map(a.Function), VisitExpr(a.Arguments[0]));
            } 
        }
 
#if ENABLE_NESTAGGREGATE 
        public virtual NestAggregate VisitNestAggregate(NestAggregate a)
        { 
            return _commandTree.CreateNestAggregate(VisitExpr(a.Arguments[0]));
        }
#endif
 
        public DbAggregate VisitAggregate(DbAggregate a)
        { 
            DbFunctionAggregate funcA = a as DbFunctionAggregate; 
            if (funcA != null)
            { 
                return VisitFunctionAggregate(funcA);
            }

#if ENABLE_NESTAGGREGATE 
            else if (a is NestAggregate)
            { 
                return VisitNestAggregate(a as NestAggregate); 
            }
#endif 
            return null;
        }

        public DbExpression VisitExpr(DbExpression expr) 
        {
            if (expr == null) 
            { 
                return null;
            } 

            return expr.Accept(this);
        }
 
        #region DbExpressionVisitor Members
 
        public override DbExpression Visit(DbExpression e) 
        {
            throw EntityUtil.NotSupported(System.Data.Entity.Strings.Cqt_General_UnsupportedExpression(e.GetType().FullName)); 
        }

        public override DbExpression Visit(DbConstantExpression e)
        { 
            return _commandTree.CreateConstantExpression(e.Value, _mapper.Map(e.ResultType));
        } 
 
        public override DbExpression Visit(DbNullExpression e)
        { 
            return _commandTree.CreateNullExpression(_mapper.Map(e.ResultType));
        }

        public override DbExpression Visit(DbVariableReferenceExpression e) 
        {
            return _commandTree.CreateVariableReferenceExpression(e.VariableName, _mapper.Map(e.ResultType)); 
        } 

        public override DbExpression Visit(DbParameterReferenceExpression e) 
        {
            return _commandTree.CreateParameterReferenceExpression(e.ParameterName);
        }
 
        public override DbExpression Visit(DbFunctionExpression e)
        { 
            if (e.IsLambda) 
            {
                List> formals = new List>(); 
                for(int idx = 0; idx < e.Function.Parameters.Count; idx++)
                {
                    FunctionParameter formal = e.Function.Parameters[idx];
                    formals.Add(new KeyValuePair(formal.Name, _mapper.Map(formal.TypeUsage))); 
                }
 
                return _commandTree.CreateLambdaFunctionExpression(formals, VisitExpr(e.LambdaBody), VisitExprList(e.Arguments)); 
            }
            else 
            {
                return _commandTree.CreateFunctionExpression(_mapper.Map(e.Function), VisitExprList(e.Arguments));
            }
        } 

#if METHOD_EXPRESSION 
        public override Expression Visit(MethodExpression e) 
        {
            if (e.Method.IsStatic) 
            {
                return _commandTree.CreateStaticMethodExpression(_mapper.Map(e.Method), VisitExprList(e.Arguments));
            }
            else 
            {
                return _commandTree.CreateInstanceMethodExpression(_mapper.Map(e.Method), VisitExpr(e.Instance), VisitExprList(e.Arguments)); 
            } 
        }
#endif 

        public override DbExpression Visit(DbPropertyExpression e)
        {
            DbExpression instanceCopy = VisitExpr(e.Instance); 
            if (Helper.IsNavigationProperty(e.Property))
            { 
                return _commandTree.CreatePropertyExpression(_mapper.Map((NavigationProperty)e.Property), instanceCopy); 
            }
            else if (Helper.IsEdmProperty(e.Property)) 
            {
                return _commandTree.CreatePropertyExpression(_mapper.Map((EdmProperty)e.Property), instanceCopy);
            }
            else 
            {
                Debug.Assert(e.Property is RelationshipEndMember, "Invalid DbPropertyExpression - Property is not EdmProperty, NavigationProperty or RelationshipEndMember"); 
                return _commandTree.CreatePropertyExpression(_mapper.Map((RelationshipEndMember)e.Property), instanceCopy); 
            }
        } 

        public override DbExpression Visit(DbComparisonExpression e)
        {
            DbExpression left = VisitExpr(e.Left); 
            DbExpression right = VisitExpr(e.Right);
 
            switch (e.ExpressionKind) 
            {
                case DbExpressionKind.Equals: 
                    return _commandTree.CreateEqualsExpression(left, right);

                case DbExpressionKind.NotEquals:
                    return _commandTree.CreateNotEqualsExpression(left, right); 

                case DbExpressionKind.LessThan: 
                    return _commandTree.CreateLessThanExpression(left, right); 

                case DbExpressionKind.GreaterThan: 
                    return _commandTree.CreateGreaterThanExpression(left, right);

                case DbExpressionKind.LessThanOrEquals:
                    return _commandTree.CreateLessThanOrEqualsExpression(left, right); 

                case DbExpressionKind.GreaterThanOrEquals: 
                    return _commandTree.CreateGreaterThanOrEqualsExpression(left, right); 

                default: 
                    return null;
            }
        }
 
        public override DbExpression Visit(DbLikeExpression e)
        { 
            return this._commandTree.CreateLikeExpression( 
                VisitExpr(e.Argument),
                VisitExpr(e.Pattern), 
                VisitExpr(e.Escape)
            );
        }
 
        public override DbExpression Visit(DbLimitExpression e)
        { 
            DbExpression argument = VisitExpr(e.Argument); 
            DbExpression limit = VisitExpr(e.Limit);
            if (e.WithTies) 
            {
                return _commandTree.CreateLimitWithTiesExpression(argument, limit);
            }
            else 
            {
                return _commandTree.CreateLimitExpression(argument, limit); 
            } 
        }
 
        public override DbExpression Visit(DbIsNullExpression e)
        {
            DbExpression operand = this.VisitExpr(e.Argument);
            return this._commandTree.CreateIsNullExpression(operand); 
        }
 
        public override DbExpression Visit(DbArithmeticExpression e) 
        {
            List args = VisitExprList(e.Arguments); 

            switch(e.ExpressionKind)
            {
                case DbExpressionKind.Plus: 
                    return _commandTree.CreatePlusExpression(args[0], args[1]);
 
                case DbExpressionKind.Minus: 
                    return _commandTree.CreateMinusExpression(args[0], args[1]);
 
                case DbExpressionKind.Multiply:
                    return _commandTree.CreateMultiplyExpression(args[0], args[1]);

                case DbExpressionKind.Divide: 
                    return _commandTree.CreateDivideExpression(args[0], args[1]);
 
                case DbExpressionKind.Modulo: 
                    return _commandTree.CreateModuloExpression(args[0], args[1]);
 
                case DbExpressionKind.UnaryMinus:
                    return _commandTree.CreateUnaryMinusExpression(args[0]);
                default:
                    return null; 
            }
        } 
 
        public override DbExpression Visit(DbAndExpression e)
        { 
            return _commandTree.CreateAndExpression(VisitExpr(e.Left), VisitExpr(e.Right));
        }

        public override DbExpression Visit(DbOrExpression e) 
        {
            return _commandTree.CreateOrExpression(VisitExpr(e.Left), VisitExpr(e.Right)); 
        } 

        public override DbExpression Visit(DbNotExpression e) 
        {
            return _commandTree.CreateNotExpression(VisitExpr(e.Argument));
        }
 
        public override DbExpression Visit(DbDistinctExpression e)
        { 
            return _commandTree.CreateDistinctExpression(VisitExpr(e.Argument)); 
        }
 
        public override DbExpression Visit(DbElementExpression e)
        {
            DbExpression arg = VisitExpr(e.Argument);
            if (e.IsSinglePropertyUnwrapped) 
            {
                return _commandTree.CreateElementExpressionUnwrapSingleProperty(arg); 
            } 
            return _commandTree.CreateElementExpression(arg);
        } 

        public override DbExpression Visit(DbIsEmptyExpression e)
        {
            return _commandTree.CreateIsEmptyExpression(VisitExpr(e.Argument)); 
        }
 
        public override DbExpression Visit(DbUnionAllExpression e) 
        {
            return _commandTree.CreateUnionAllExpression(VisitExpr(e.Left), VisitExpr(e.Right)); 
        }

        public override DbExpression Visit(DbIntersectExpression e)
        { 
            return _commandTree.CreateIntersectExpression(VisitExpr(e.Left), VisitExpr(e.Right));
        } 
 
        public override DbExpression Visit(DbExceptExpression e)
        { 
            return _commandTree.CreateExceptExpression(VisitExpr(e.Left), VisitExpr(e.Right));
        }

        public override DbExpression Visit(DbTreatExpression e) 
        {
            return _commandTree.CreateTreatExpression(VisitExpr(e.Argument), _mapper.Map(e.ResultType)); 
        } 

        public override DbExpression Visit(DbCastExpression e) 
        {
            return _commandTree.CreateCastExpression(VisitExpr(e.Argument), _mapper.Map(e.ResultType));
        }
 
        public override DbExpression Visit(DbIsOfExpression e)
        { 
            if (DbExpressionKind.IsOfOnly == e.ExpressionKind) 
            {
                return _commandTree.CreateIsOfOnlyExpression(VisitExpr(e.Argument), _mapper.Map(e.OfType)); 
            }
            else
            {
                return _commandTree.CreateIsOfExpression(VisitExpr(e.Argument), _mapper.Map(e.OfType)); 
            }
        } 
 
        public override DbExpression Visit(DbOfTypeExpression e)
        { 
            DbExpression arg = VisitExpr(e.Argument);
            TypeUsage ofType = _mapper.Map(e.OfType);

            if (DbExpressionKind.OfTypeOnly == e.ExpressionKind) 
            {
                return _commandTree.CreateOfTypeOnlyExpression(arg, ofType); 
            } 
            else
            { 
                return _commandTree.CreateOfTypeExpression(arg, ofType);
            }
        }
 
        public override DbExpression Visit(DbCaseExpression e)
        { 
            return _commandTree.CreateCaseExpression(VisitExprList(e.When), VisitExprList(e.Then), VisitExpr(e.Else)); 
        }
 
        public override DbExpression Visit(DbNewInstanceExpression e)
        {
            TypeUsage resultType = _mapper.Map(e.ResultType);
            List args = VisitExprList(e.Arguments); 
            if (resultType.EdmType.BuiltInTypeKind == BuiltInTypeKind.EntityType &&
               e.HasRelatedEntityReferences) 
            { 
                List relatedRefs = new List(e.RelatedEntityReferences.Count);
                for(int idx = 0; idx < e.RelatedEntityReferences.Count; idx++) 
                {
                    DbRelatedEntityRef sourceRef = e.RelatedEntityReferences[idx];

                    RelationshipEndMember fromEnd = _mapper.Map(sourceRef.SourceEnd) as RelationshipEndMember; 
                    Debug.Assert(fromEnd != null, "Unable to map 'source' relation end property using ExpressionCopier's metadata mapper");
 
                    RelationshipEndMember toEnd = _mapper.Map(sourceRef.TargetEnd) as RelationshipEndMember; 
                    Debug.Assert(fromEnd != null, "Unable to map 'target' relation end property using ExpressionCopier's metadata mapper");
 
                    DbExpression targetRef = this.VisitExpr(sourceRef.TargetEntityReference);

                    relatedRefs.Add(_commandTree.CreateRelatedEntityRef(fromEnd, toEnd, targetRef));
                } 

                return _commandTree.CreateNewEntityWithRelationshipsExpression((EntityType)resultType.EdmType, args, relatedRefs); 
            } 
            else
            { 
                return _commandTree.CreateNewInstanceExpression(resultType, args);
            }
        }
 
        public override DbExpression Visit(DbRefExpression e)
        { 
            RefType refType = TypeHelpers.GetEdmType(e.ResultType); 
            EntityTypeBase targetType = refType.ElementType;
 
            return _commandTree.CreateRefExpression(_mapper.Map(e.EntitySet), VisitExpr(e.Argument), (EntityType)_mapper.Map(targetType));
        }

        public override DbExpression Visit(DbRelationshipNavigationExpression e) 
        {
            RelationshipEndMember fromEnd = _mapper.Map(e.NavigateFrom) as RelationshipEndMember; 
            Debug.Assert(fromEnd != null, "Unable to map 'from' relation end property using ExpressionCopier's metadata mapper"); 

            RelationshipEndMember toEnd = _mapper.Map(e.NavigateTo) as RelationshipEndMember; 
            Debug.Assert(fromEnd != null, "Unable to map 'to' relation end property using ExpressionCopier's metadata mapper");

            return _commandTree.CreateRelationshipNavigationExpression(fromEnd, toEnd, VisitExpr(e.NavigationSource));
        } 

        public override DbExpression Visit(DbDerefExpression e) 
        { 
            return _commandTree.CreateDerefExpression(VisitExpr(e.Argument));
        } 

        public override DbExpression Visit(DbRefKeyExpression e)
        {
            return _commandTree.CreateRefKeyExpression(VisitExpr(e.Argument)); 
        }
 
        public override DbExpression Visit(DbEntityRefExpression e) 
        {
            return _commandTree.CreateEntityRefExpression(VisitExpr(e.Argument)); 
        }

        public override DbExpression Visit(DbScanExpression e)
        { 
            return _commandTree.CreateScanExpression(_mapper.Map(e.Target));
        } 
 
        public override DbExpression Visit(DbFilterExpression e)
        { 
            return _commandTree.CreateFilterExpression(VisitBinding(e.Input), VisitExpr(e.Predicate));
        }

        public override DbExpression Visit(DbProjectExpression e) 
        {
            return _commandTree.CreateProjectExpression(VisitBinding(e.Input),  VisitExpr(e.Projection)); 
        } 

        public override DbExpression Visit(DbCrossJoinExpression e) 
        {
            return _commandTree.CreateCrossJoinExpression(VisitBindingList(e.Inputs));
        }
 
        public override DbExpression Visit(DbJoinExpression e)
        { 
            return _commandTree.CreateJoinExpressionByKind( 
                e.ExpressionKind,
                VisitExpr(e.JoinCondition), 
                VisitBinding(e.Left),
                VisitBinding(e.Right)
            );
        } 

        public override DbExpression Visit(DbApplyExpression e) 
        { 
            return _commandTree.CreateApplyExpressionByKind
            ( 
                e.ExpressionKind,
                VisitBinding(e.Input),
                VisitBinding(e.Apply)
            ); 
        }
 
        public override DbExpression Visit(DbGroupByExpression e) 
        {
            List> keys = new List>(); 
            List> aggs = new List>();

            Debug.Assert(TypeSemantics.IsCollectionType(e.ResultType), "ExpressionCopier encountered DbGroupByExpression with non-collection result type");
            CollectionType resultType = TypeHelpers.GetEdmType(_mapper.Map(e.ResultType)); 

            Debug.Assert(TypeSemantics.IsRowType(resultType.TypeUsage), "ExpressionCopier encountered DbGroupByExpression with non-record result element type"); 
            RowType resultElementType = TypeHelpers.GetEdmType(resultType.TypeUsage); 

            ReadOnlyMetadataCollection cols = resultElementType.Properties; 

            int iColPos = 0;
            for(int idx = 0; idx < e.Keys.Count; idx++)
            { 
                keys.Add(new KeyValuePair(cols[iColPos].Name, VisitExpr(e.Keys[idx])));
                iColPos++; 
            } 

            for(int idx = 0; idx < e.Aggregates.Count; idx++) 
            {
                aggs.Add(new KeyValuePair(cols[iColPos].Name, VisitAggregate(e.Aggregates[idx])));
                iColPos++;
            } 

            return _commandTree.CreateGroupByExpression 
            ( 
                this.VisitGroupExpressionBinding(e.Input),
                keys, 
                aggs
            );
        }
 
        public override DbExpression Visit(DbSkipExpression e)
        { 
            return _commandTree.CreateSkipExpression(VisitBinding(e.Input), VisitSortOrder(e.SortOrder), VisitExpr(e.Count)); 
        }
 
        public override DbExpression Visit(DbSortExpression e)
        {
            return _commandTree.CreateSortExpression(VisitBinding(e.Input), VisitSortOrder(e.SortOrder));
        } 

        public override DbExpression Visit(DbQuantifierExpression e) 
        { 
            DbExpressionBinding eb = VisitBinding(e.Input);
            DbExpression pred = VisitExpr(e.Predicate); 

            if (e.ExpressionKind == DbExpressionKind.Any)
            {
                return _commandTree.CreateAnyExpression(eb, pred); 
            }
            else 
            { 
                return _commandTree.CreateAllExpression(eb, pred);
            } 
        }
        #endregion
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....], [....]
//--------------------------------------------------------------------- 
 
using System;
using System.Collections.Generic; 
using System.Diagnostics;
using System.Globalization;

using System.Data.Common; 
using System.Data.Metadata.Edm;
using System.Data.Common.CommandTrees; 
 
namespace System.Data.Common.CommandTrees.Internal
{ 
    /// 
    /// Clones an expression tree
    /// 
    internal class ExpressionCopier : DbExpressionVisitor 
    {
        ///  
        /// The MetadataMapper class is a helper class that logically translates 
        /// metadata constructs from one space to another. The objects that are translated
        /// include 
        ///   Types
        ///   Properties
        ///   Methods
        ///   Functions 
        ///   Extents
        ///   EntitySets 
        /// The default implementation is to simply return the specified metadata instance 
        /// (an 'identity' mapping)
        ///  
        protected class MetadataMapper
        {
            internal static readonly MetadataMapper IdentityMapper = new MetadataMapper();
 
            internal MetadataMapper() {}
 
            internal virtual EdmType                Map(EdmType s) { return s; } 
            internal virtual EntitySetBase          Map(EntitySetBase e) { return e; }
            internal virtual EntitySet              Map(EntitySet e) { return e; } 
            internal virtual EdmFunction            Map(EdmFunction f) { return f; }
            internal virtual NavigationProperty     Map(NavigationProperty p) { return p; }
            internal virtual EdmProperty            Map(EdmProperty p) { return p; }
            internal virtual RelationshipEndMember  Map(RelationshipEndMember m) { return m; } 
            internal virtual TypeUsage              Map(TypeUsage t) { return t; }
 
#if METHOD_EXPRESSION 
            internal virtual MethodMetadata    Map(MethodMetadata m) { return m; }
#endif 

        }

        private class WorkspaceMapper : MetadataMapper 
        {
            private MetadataWorkspace _metadata; 
            private Dictionary _transientTypes = new Dictionary(); 

            internal WorkspaceMapper(MetadataWorkspace destinationWorkspace) 
                : base()
            {
                _metadata = destinationWorkspace;
            } 

            #region MetadataMapper Overrides 
 
            internal override EdmType Map(EdmType type)
            { 
                EdmType retType = null;

                if (BuiltInTypeKind.RefType == type.BuiltInTypeKind)
                { 
                    RefType refType = (RefType)type;
                    retType = new RefType((EntityType)Map(refType.ElementType)); 
                } 
                else if (BuiltInTypeKind.CollectionType == type.BuiltInTypeKind)
                { 
                    CollectionType collectionType = (CollectionType)type;
                    retType = new CollectionType(Map(collectionType.TypeUsage));
                }
                else if (BuiltInTypeKind.RowType == type.BuiltInTypeKind) 
                {
                    RowType rowType = (RowType)type; 
                    List columns = new List(); 
                    foreach (EdmProperty p in rowType.Properties)
                    { 
                        columns.Add(new EdmProperty(p.Name, Map(p.TypeUsage)));
                    }

                    RowType newRowType = new RowType(columns, rowType.InitializerMetadata); 
                    retType = newRowType;
                } 
                else 
                {
                    if (!_metadata.TryGetType(type.Name, type.NamespaceName, type.DataSpace, out retType) || 
                        null == retType)
                    {

                        throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_TypeNotFound(TypeHelpers.GetFullName(type))); 
                    }
                } 
 
                return retType;
            } 

            internal override EntitySetBase Map(EntitySetBase e)
            {
                EntityContainer container; 
                if (_metadata.TryGetEntityContainer(e.EntityContainer.Name, e.EntityContainer.DataSpace, out container))
                { 
                    EntitySetBase extent = null; 
                    if (container.BaseEntitySets.TryGetValue(e.Name, false, out extent) &&
                        extent != null) 
                    {
                        return extent;
                    }
 
                    throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EntitySetNotFound(e.EntityContainer.Name, e.Name));
                } 
 
                throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EntityContainerNotFound(e.EntityContainer.Name));
            } 

            internal override EntitySet Map(EntitySet e)
            {
                EntityContainer container; 
                if(_metadata.TryGetEntityContainer(e.EntityContainer.Name, e.EntityContainer.DataSpace, out container))
                { 
                    EntitySetBase set = null; 
                    if (container.BaseEntitySets.TryGetValue(e.Name, false, out set))
                    { 
                        EntitySet entitySet = set as EntitySet;
                        if (entitySet != null)
                        {
                            return entitySet; 
                        }
                    } 
 
                    throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EntitySetNotFound(e.EntityContainer.Name, e.Name));
                } 

                throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EntityContainerNotFound(e.EntityContainer.Name));
            }
 
            internal override EdmFunction Map(EdmFunction f)
            { 
                TypeUsage[] paramTypes = new TypeUsage[f.Parameters.Count]; 
                int idx = 0;
                foreach (FunctionParameter p in f.Parameters) 
                {
                    paramTypes[idx] = Map(p.TypeUsage);
                    idx++;
                } 

                EdmFunction retFunc = null; 
                if( _metadata.TryGetFunction(f.Name, f.NamespaceName, paramTypes, false, f.DataSpace, out retFunc) && 
                    retFunc != null)
                { 
                    return retFunc;
                }

                throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_FunctionNotFound(TypeHelpers.GetFullName(f))); 
            }
 
            internal override NavigationProperty Map(NavigationProperty prop) 
            {
                NavigationProperty retProp; 
                if (!TryMapMember(prop, out retProp))
                {
                    throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_PropertyNotFound(prop.Name, TypeHelpers.GetFullName(prop.DeclaringType)));
                } 
                return retProp;
            } 
 
            internal override EdmProperty Map(EdmProperty prop)
            { 
                EdmProperty retProp;
                if (!TryMapMember(prop, out retProp))
                {
                    throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_PropertyNotFound(prop.Name, TypeHelpers.GetFullName(prop.DeclaringType))); 
                }
                return retProp; 
            } 

            internal override RelationshipEndMember Map(RelationshipEndMember end) 
            {
                RelationshipEndMember retEnd;
                if (!TryMapMember(end, out retEnd))
                { 
                    throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EndNotFound(end.Name, TypeHelpers.GetFullName(end.DeclaringType)));
                } 
 
                return retEnd;
            } 

            private bool TryMapMember(TMemberType prop, out TMemberType foundProp) where TMemberType : EdmMember
            {
                foundProp = null; 
                StructuralType mappedType = Map(prop.DeclaringType) as StructuralType;
                if (mappedType != null) 
                { 
                    EdmMember foundMember = null;
                    if (mappedType.Members.TryGetValue(prop.Name, false, out foundMember)) 
                    {
                        foundProp = foundMember as TMemberType;
                    }
                } 

                return (foundProp != null); 
            } 

#if METHOD_EXPRESSION 
            internal override MethodMetadata Map(MethodMetadata meth)
            {
                MethodMetadata retMethod = null;
 
                List mappedParamTypes = new List();
                foreach (IParameterMetadata methParam in meth.Parameters) 
                { 
                    mappedParamTypes.Add(this.Map(methParam.Type));
                } 

                TypeMetadata mappedType = this.Map(meth.DefiningType);
                foreach (MemberMetadata member in mappedType.GetMemberByName(meth.Name))
                { 
                    // Ignore the member if:
                    // - It's not a method, OR 
                    // - It's IsStatic property doesn't match, OR 
                    // - It doesn't declare the right number of parameters.
                    MethodMetadata mappedMeth = member as MethodMetadata; 
                    if( null == mappedMeth ||
                        mappedMeth.IsStatic != meth.IsStatic ||
                        mappedMeth.Parameters.Count != mappedParamTypes.Count)
                    { 
                        continue;
                    } 
 
                    // Assume that the method matches, which is correct for the case
                    // where the required method and this method both declare no parameters. 
                    bool paramMatch = true;
                    for (int idx = 0; idx < mappedParamTypes.Count; idx++)
                    {
                        // If the type of any parameter to the method under consideration 
                        // does not match the type of the corresponding parameter from the
                        // source method, then this cannot be the correct destination method. 
                        if (!mappedParamTypes[idx].Equals(mappedMeth.Parameters[idx].Type)) 
                        {
                            paramMatch = false; 
                            break;
                        }
                    }
 
                    // If any of the parameter types didn't match then move on.
                    if (!paramMatch) 
                    { 
                        continue;
                    } 

                    // This is the required method.
                    retMethod = mappedMeth;
                    break; 
                }
 
                if (null == retMethod) 
                {
                    throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_MethodNotFound(meth.Name, mappedType.FullName)); 
                }

                return retMethod;
            } 
#endif
 
            internal override TypeUsage Map(TypeUsage type) 
            {
                // 
                // If the target metatadata workspace contains the same type instances, then the type does not
                // need to be 'mapped' and the same TypeUsage instance may be returned. This can happen if the
                // target workspace and the workspace of the source Command Tree are using the same ItemCollection.
                // 
                EdmType retEdmType = Map(type.EdmType);
                if (object.ReferenceEquals(retEdmType, type.EdmType)) 
                { 
                    return type;
                } 

                //
                // Retrieve the Facets from this type usage so that
                // 1) They can be used to map the type if it is a primitive type 
                // 2) They can be applied to the new type usage that references the mapped type
                // 
                Facet[] facets = new Facet[type.Facets.Count]; 
                int idx = 0;
                foreach (Facet f in type.Facets) 
                {
                    facets[idx] = f;
                    idx++;
                } 

                return TypeUsage.Create(retEdmType, facets); 
            } 
            #endregion
        } 

        private MetadataMapper _mapper;
        private DbCommandTree _commandTree;
 
        protected DbCommandTree CommandTree
        { 
            get { return this._commandTree; } 
        }
 
        protected ExpressionCopier(DbCommandTree commandTree, MetadataMapper mapper)
        {
            _commandTree = commandTree;
            _mapper = mapper; 
        }
 
        private static MetadataMapper GetMapper(MetadataWorkspace source, MetadataWorkspace destination) 
        {
            ItemCollection mappingItemCollection = source.GetItemCollection(DataSpace.CSSpace); 
            ItemCollection destinationMappingItemCollection = destination.GetItemCollection(DataSpace.CSSpace);

            if (!object.ReferenceEquals(mappingItemCollection, destinationMappingItemCollection))
            { 
                EntityBid.Trace(" Using cross-workspace metadata mapper\n");
                return new WorkspaceMapper(destination); 
            } 

            EntityBid.Trace(" Using identity metadata mapper\n"); 
            return MetadataMapper.IdentityMapper;
        }

        internal static DbExpression Copy(DbCommandTree destination, DbExpression expression) 
        {
            Debug.Assert(destination != null, "Destination Command Tree is null"); 
            Debug.Assert(expression != null, "DbExpression is null"); 

            using(new EntityBid.ScopeAuto(" destination=%d#", destination.ObjectId)) 
            {
                EntityBid.Trace(" expression=%d#, %d{cqt.DbExpressionKind}\n", DbExpression.GetObjectId(expression), DbExpression.GetExpressionKind(expression));

                ExpressionCopier copier = new ExpressionCopier(destination, GetMapper(expression.CommandTree.MetadataWorkspace, destination.MetadataWorkspace)); 
                return copier.VisitExpr(expression);
            } 
        } 

        public List VisitList(IList exprList) where T: DbExpression 
        {
            List retList = null;
            if (exprList != null)
            { 
                retList = new List();
                for (int idx = 0; idx < exprList.Count; idx++) 
                { 
                    retList.Add((T)this.VisitExpr(exprList[idx]));
                } 
            }

            return retList;
        } 
        public List VisitExprList(IList exprList)
        { 
            return VisitList(exprList); 
        }
 
        public DbExpressionBinding VisitBinding(DbExpressionBinding b)
        {
            DbExpression newExpr = VisitExpr(b.Expression);
            return this._commandTree.CreateExpressionBinding(newExpr, b.VariableName); 
        }
 
        public DbGroupExpressionBinding VisitGroupExpressionBinding(DbGroupExpressionBinding gb) 
        {
            DbExpression newExpr = VisitExpr(gb.Expression); 
            return this._commandTree.CreateGroupExpressionBinding(newExpr, gb.VariableName, gb.GroupVariableName);
        }

        public List VisitBindingList(IList bindingList) 
        {
            List retList = null; 
            if (bindingList != null) 
            {
                retList = new List(); 
                for (int idx = 0; idx < bindingList.Count; idx++)
                {
                    retList.Add(this.VisitBinding(bindingList[idx]));
                } 
            }
 
            return retList; 
        }
 
        public List VisitSortOrder(IList sortOrder)
        {
            List skeys = new List();
            for(int idx = 0; idx < sortOrder.Count; idx++) 
            {
                DbSortClause s = sortOrder[idx]; 
                DbExpression keyExpr = VisitExpr(s.Expression); 
                bool asc = s.Ascending;
                if(!string.IsNullOrEmpty(s.Collation)) 
                {
                    skeys.Add(_commandTree.CreateSortClause(keyExpr, asc, s.Collation));
                }
                else 
                {
                    skeys.Add(_commandTree.CreateSortClause(keyExpr, asc)); 
                } 
            }
 
            return skeys;
        }

        public virtual DbFunctionAggregate VisitFunctionAggregate(DbFunctionAggregate a) 
        {
            if (a.Distinct) 
            { 
                return _commandTree.CreateDistinctFunctionAggregate(_mapper.Map(a.Function), VisitExpr(a.Arguments[0]));
            } 
            else
            {
                return _commandTree.CreateFunctionAggregate(_mapper.Map(a.Function), VisitExpr(a.Arguments[0]));
            } 
        }
 
#if ENABLE_NESTAGGREGATE 
        public virtual NestAggregate VisitNestAggregate(NestAggregate a)
        { 
            return _commandTree.CreateNestAggregate(VisitExpr(a.Arguments[0]));
        }
#endif
 
        public DbAggregate VisitAggregate(DbAggregate a)
        { 
            DbFunctionAggregate funcA = a as DbFunctionAggregate; 
            if (funcA != null)
            { 
                return VisitFunctionAggregate(funcA);
            }

#if ENABLE_NESTAGGREGATE 
            else if (a is NestAggregate)
            { 
                return VisitNestAggregate(a as NestAggregate); 
            }
#endif 
            return null;
        }

        public DbExpression VisitExpr(DbExpression expr) 
        {
            if (expr == null) 
            { 
                return null;
            } 

            return expr.Accept(this);
        }
 
        #region DbExpressionVisitor Members
 
        public override DbExpression Visit(DbExpression e) 
        {
            throw EntityUtil.NotSupported(System.Data.Entity.Strings.Cqt_General_UnsupportedExpression(e.GetType().FullName)); 
        }

        public override DbExpression Visit(DbConstantExpression e)
        { 
            return _commandTree.CreateConstantExpression(e.Value, _mapper.Map(e.ResultType));
        } 
 
        public override DbExpression Visit(DbNullExpression e)
        { 
            return _commandTree.CreateNullExpression(_mapper.Map(e.ResultType));
        }

        public override DbExpression Visit(DbVariableReferenceExpression e) 
        {
            return _commandTree.CreateVariableReferenceExpression(e.VariableName, _mapper.Map(e.ResultType)); 
        } 

        public override DbExpression Visit(DbParameterReferenceExpression e) 
        {
            return _commandTree.CreateParameterReferenceExpression(e.ParameterName);
        }
 
        public override DbExpression Visit(DbFunctionExpression e)
        { 
            if (e.IsLambda) 
            {
                List> formals = new List>(); 
                for(int idx = 0; idx < e.Function.Parameters.Count; idx++)
                {
                    FunctionParameter formal = e.Function.Parameters[idx];
                    formals.Add(new KeyValuePair(formal.Name, _mapper.Map(formal.TypeUsage))); 
                }
 
                return _commandTree.CreateLambdaFunctionExpression(formals, VisitExpr(e.LambdaBody), VisitExprList(e.Arguments)); 
            }
            else 
            {
                return _commandTree.CreateFunctionExpression(_mapper.Map(e.Function), VisitExprList(e.Arguments));
            }
        } 

#if METHOD_EXPRESSION 
        public override Expression Visit(MethodExpression e) 
        {
            if (e.Method.IsStatic) 
            {
                return _commandTree.CreateStaticMethodExpression(_mapper.Map(e.Method), VisitExprList(e.Arguments));
            }
            else 
            {
                return _commandTree.CreateInstanceMethodExpression(_mapper.Map(e.Method), VisitExpr(e.Instance), VisitExprList(e.Arguments)); 
            } 
        }
#endif 

        public override DbExpression Visit(DbPropertyExpression e)
        {
            DbExpression instanceCopy = VisitExpr(e.Instance); 
            if (Helper.IsNavigationProperty(e.Property))
            { 
                return _commandTree.CreatePropertyExpression(_mapper.Map((NavigationProperty)e.Property), instanceCopy); 
            }
            else if (Helper.IsEdmProperty(e.Property)) 
            {
                return _commandTree.CreatePropertyExpression(_mapper.Map((EdmProperty)e.Property), instanceCopy);
            }
            else 
            {
                Debug.Assert(e.Property is RelationshipEndMember, "Invalid DbPropertyExpression - Property is not EdmProperty, NavigationProperty or RelationshipEndMember"); 
                return _commandTree.CreatePropertyExpression(_mapper.Map((RelationshipEndMember)e.Property), instanceCopy); 
            }
        } 

        public override DbExpression Visit(DbComparisonExpression e)
        {
            DbExpression left = VisitExpr(e.Left); 
            DbExpression right = VisitExpr(e.Right);
 
            switch (e.ExpressionKind) 
            {
                case DbExpressionKind.Equals: 
                    return _commandTree.CreateEqualsExpression(left, right);

                case DbExpressionKind.NotEquals:
                    return _commandTree.CreateNotEqualsExpression(left, right); 

                case DbExpressionKind.LessThan: 
                    return _commandTree.CreateLessThanExpression(left, right); 

                case DbExpressionKind.GreaterThan: 
                    return _commandTree.CreateGreaterThanExpression(left, right);

                case DbExpressionKind.LessThanOrEquals:
                    return _commandTree.CreateLessThanOrEqualsExpression(left, right); 

                case DbExpressionKind.GreaterThanOrEquals: 
                    return _commandTree.CreateGreaterThanOrEqualsExpression(left, right); 

                default: 
                    return null;
            }
        }
 
        public override DbExpression Visit(DbLikeExpression e)
        { 
            return this._commandTree.CreateLikeExpression( 
                VisitExpr(e.Argument),
                VisitExpr(e.Pattern), 
                VisitExpr(e.Escape)
            );
        }
 
        public override DbExpression Visit(DbLimitExpression e)
        { 
            DbExpression argument = VisitExpr(e.Argument); 
            DbExpression limit = VisitExpr(e.Limit);
            if (e.WithTies) 
            {
                return _commandTree.CreateLimitWithTiesExpression(argument, limit);
            }
            else 
            {
                return _commandTree.CreateLimitExpression(argument, limit); 
            } 
        }
 
        public override DbExpression Visit(DbIsNullExpression e)
        {
            DbExpression operand = this.VisitExpr(e.Argument);
            return this._commandTree.CreateIsNullExpression(operand); 
        }
 
        public override DbExpression Visit(DbArithmeticExpression e) 
        {
            List args = VisitExprList(e.Arguments); 

            switch(e.ExpressionKind)
            {
                case DbExpressionKind.Plus: 
                    return _commandTree.CreatePlusExpression(args[0], args[1]);
 
                case DbExpressionKind.Minus: 
                    return _commandTree.CreateMinusExpression(args[0], args[1]);
 
                case DbExpressionKind.Multiply:
                    return _commandTree.CreateMultiplyExpression(args[0], args[1]);

                case DbExpressionKind.Divide: 
                    return _commandTree.CreateDivideExpression(args[0], args[1]);
 
                case DbExpressionKind.Modulo: 
                    return _commandTree.CreateModuloExpression(args[0], args[1]);
 
                case DbExpressionKind.UnaryMinus:
                    return _commandTree.CreateUnaryMinusExpression(args[0]);
                default:
                    return null; 
            }
        } 
 
        public override DbExpression Visit(DbAndExpression e)
        { 
            return _commandTree.CreateAndExpression(VisitExpr(e.Left), VisitExpr(e.Right));
        }

        public override DbExpression Visit(DbOrExpression e) 
        {
            return _commandTree.CreateOrExpression(VisitExpr(e.Left), VisitExpr(e.Right)); 
        } 

        public override DbExpression Visit(DbNotExpression e) 
        {
            return _commandTree.CreateNotExpression(VisitExpr(e.Argument));
        }
 
        public override DbExpression Visit(DbDistinctExpression e)
        { 
            return _commandTree.CreateDistinctExpression(VisitExpr(e.Argument)); 
        }
 
        public override DbExpression Visit(DbElementExpression e)
        {
            DbExpression arg = VisitExpr(e.Argument);
            if (e.IsSinglePropertyUnwrapped) 
            {
                return _commandTree.CreateElementExpressionUnwrapSingleProperty(arg); 
            } 
            return _commandTree.CreateElementExpression(arg);
        } 

        public override DbExpression Visit(DbIsEmptyExpression e)
        {
            return _commandTree.CreateIsEmptyExpression(VisitExpr(e.Argument)); 
        }
 
        public override DbExpression Visit(DbUnionAllExpression e) 
        {
            return _commandTree.CreateUnionAllExpression(VisitExpr(e.Left), VisitExpr(e.Right)); 
        }

        public override DbExpression Visit(DbIntersectExpression e)
        { 
            return _commandTree.CreateIntersectExpression(VisitExpr(e.Left), VisitExpr(e.Right));
        } 
 
        public override DbExpression Visit(DbExceptExpression e)
        { 
            return _commandTree.CreateExceptExpression(VisitExpr(e.Left), VisitExpr(e.Right));
        }

        public override DbExpression Visit(DbTreatExpression e) 
        {
            return _commandTree.CreateTreatExpression(VisitExpr(e.Argument), _mapper.Map(e.ResultType)); 
        } 

        public override DbExpression Visit(DbCastExpression e) 
        {
            return _commandTree.CreateCastExpression(VisitExpr(e.Argument), _mapper.Map(e.ResultType));
        }
 
        public override DbExpression Visit(DbIsOfExpression e)
        { 
            if (DbExpressionKind.IsOfOnly == e.ExpressionKind) 
            {
                return _commandTree.CreateIsOfOnlyExpression(VisitExpr(e.Argument), _mapper.Map(e.OfType)); 
            }
            else
            {
                return _commandTree.CreateIsOfExpression(VisitExpr(e.Argument), _mapper.Map(e.OfType)); 
            }
        } 
 
        public override DbExpression Visit(DbOfTypeExpression e)
        { 
            DbExpression arg = VisitExpr(e.Argument);
            TypeUsage ofType = _mapper.Map(e.OfType);

            if (DbExpressionKind.OfTypeOnly == e.ExpressionKind) 
            {
                return _commandTree.CreateOfTypeOnlyExpression(arg, ofType); 
            } 
            else
            { 
                return _commandTree.CreateOfTypeExpression(arg, ofType);
            }
        }
 
        public override DbExpression Visit(DbCaseExpression e)
        { 
            return _commandTree.CreateCaseExpression(VisitExprList(e.When), VisitExprList(e.Then), VisitExpr(e.Else)); 
        }
 
        public override DbExpression Visit(DbNewInstanceExpression e)
        {
            TypeUsage resultType = _mapper.Map(e.ResultType);
            List args = VisitExprList(e.Arguments); 
            if (resultType.EdmType.BuiltInTypeKind == BuiltInTypeKind.EntityType &&
               e.HasRelatedEntityReferences) 
            { 
                List relatedRefs = new List(e.RelatedEntityReferences.Count);
                for(int idx = 0; idx < e.RelatedEntityReferences.Count; idx++) 
                {
                    DbRelatedEntityRef sourceRef = e.RelatedEntityReferences[idx];

                    RelationshipEndMember fromEnd = _mapper.Map(sourceRef.SourceEnd) as RelationshipEndMember; 
                    Debug.Assert(fromEnd != null, "Unable to map 'source' relation end property using ExpressionCopier's metadata mapper");
 
                    RelationshipEndMember toEnd = _mapper.Map(sourceRef.TargetEnd) as RelationshipEndMember; 
                    Debug.Assert(fromEnd != null, "Unable to map 'target' relation end property using ExpressionCopier's metadata mapper");
 
                    DbExpression targetRef = this.VisitExpr(sourceRef.TargetEntityReference);

                    relatedRefs.Add(_commandTree.CreateRelatedEntityRef(fromEnd, toEnd, targetRef));
                } 

                return _commandTree.CreateNewEntityWithRelationshipsExpression((EntityType)resultType.EdmType, args, relatedRefs); 
            } 
            else
            { 
                return _commandTree.CreateNewInstanceExpression(resultType, args);
            }
        }
 
        public override DbExpression Visit(DbRefExpression e)
        { 
            RefType refType = TypeHelpers.GetEdmType(e.ResultType); 
            EntityTypeBase targetType = refType.ElementType;
 
            return _commandTree.CreateRefExpression(_mapper.Map(e.EntitySet), VisitExpr(e.Argument), (EntityType)_mapper.Map(targetType));
        }

        public override DbExpression Visit(DbRelationshipNavigationExpression e) 
        {
            RelationshipEndMember fromEnd = _mapper.Map(e.NavigateFrom) as RelationshipEndMember; 
            Debug.Assert(fromEnd != null, "Unable to map 'from' relation end property using ExpressionCopier's metadata mapper"); 

            RelationshipEndMember toEnd = _mapper.Map(e.NavigateTo) as RelationshipEndMember; 
            Debug.Assert(fromEnd != null, "Unable to map 'to' relation end property using ExpressionCopier's metadata mapper");

            return _commandTree.CreateRelationshipNavigationExpression(fromEnd, toEnd, VisitExpr(e.NavigationSource));
        } 

        public override DbExpression Visit(DbDerefExpression e) 
        { 
            return _commandTree.CreateDerefExpression(VisitExpr(e.Argument));
        } 

        public override DbExpression Visit(DbRefKeyExpression e)
        {
            return _commandTree.CreateRefKeyExpression(VisitExpr(e.Argument)); 
        }
 
        public override DbExpression Visit(DbEntityRefExpression e) 
        {
            return _commandTree.CreateEntityRefExpression(VisitExpr(e.Argument)); 
        }

        public override DbExpression Visit(DbScanExpression e)
        { 
            return _commandTree.CreateScanExpression(_mapper.Map(e.Target));
        } 
 
        public override DbExpression Visit(DbFilterExpression e)
        { 
            return _commandTree.CreateFilterExpression(VisitBinding(e.Input), VisitExpr(e.Predicate));
        }

        public override DbExpression Visit(DbProjectExpression e) 
        {
            return _commandTree.CreateProjectExpression(VisitBinding(e.Input),  VisitExpr(e.Projection)); 
        } 

        public override DbExpression Visit(DbCrossJoinExpression e) 
        {
            return _commandTree.CreateCrossJoinExpression(VisitBindingList(e.Inputs));
        }
 
        public override DbExpression Visit(DbJoinExpression e)
        { 
            return _commandTree.CreateJoinExpressionByKind( 
                e.ExpressionKind,
                VisitExpr(e.JoinCondition), 
                VisitBinding(e.Left),
                VisitBinding(e.Right)
            );
        } 

        public override DbExpression Visit(DbApplyExpression e) 
        { 
            return _commandTree.CreateApplyExpressionByKind
            ( 
                e.ExpressionKind,
                VisitBinding(e.Input),
                VisitBinding(e.Apply)
            ); 
        }
 
        public override DbExpression Visit(DbGroupByExpression e) 
        {
            List> keys = new List>(); 
            List> aggs = new List>();

            Debug.Assert(TypeSemantics.IsCollectionType(e.ResultType), "ExpressionCopier encountered DbGroupByExpression with non-collection result type");
            CollectionType resultType = TypeHelpers.GetEdmType(_mapper.Map(e.ResultType)); 

            Debug.Assert(TypeSemantics.IsRowType(resultType.TypeUsage), "ExpressionCopier encountered DbGroupByExpression with non-record result element type"); 
            RowType resultElementType = TypeHelpers.GetEdmType(resultType.TypeUsage); 

            ReadOnlyMetadataCollection cols = resultElementType.Properties; 

            int iColPos = 0;
            for(int idx = 0; idx < e.Keys.Count; idx++)
            { 
                keys.Add(new KeyValuePair(cols[iColPos].Name, VisitExpr(e.Keys[idx])));
                iColPos++; 
            } 

            for(int idx = 0; idx < e.Aggregates.Count; idx++) 
            {
                aggs.Add(new KeyValuePair(cols[iColPos].Name, VisitAggregate(e.Aggregates[idx])));
                iColPos++;
            } 

            return _commandTree.CreateGroupByExpression 
            ( 
                this.VisitGroupExpressionBinding(e.Input),
                keys, 
                aggs
            );
        }
 
        public override DbExpression Visit(DbSkipExpression e)
        { 
            return _commandTree.CreateSkipExpression(VisitBinding(e.Input), VisitSortOrder(e.SortOrder), VisitExpr(e.Count)); 
        }
 
        public override DbExpression Visit(DbSortExpression e)
        {
            return _commandTree.CreateSortExpression(VisitBinding(e.Input), VisitSortOrder(e.SortOrder));
        } 

        public override DbExpression Visit(DbQuantifierExpression e) 
        { 
            DbExpressionBinding eb = VisitBinding(e.Input);
            DbExpression pred = VisitExpr(e.Predicate); 

            if (e.ExpressionKind == DbExpressionKind.Any)
            {
                return _commandTree.CreateAnyExpression(eb, pred); 
            }
            else 
            { 
                return _commandTree.CreateAllExpression(eb, pred);
            } 
        }
        #endregion
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK