ExpressionCopier.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Common / CommandTrees / Internal / ExpressionCopier.cs / 1305376 / ExpressionCopier.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

using System; 
using System.Collections.Generic;
using System.Data.Common;
using System.Data.Metadata.Edm;
using System.Data.Common.CommandTrees; 
using System.Data.Common.CommandTrees.ExpressionBuilder;
using System.Diagnostics; 
using System.Globalization; 
using System.Linq;
using System.Data.Common.EntitySql; 

namespace System.Data.Common.CommandTrees.Internal
{
    ///  
    /// Ensures that all metadata in a given expression tree is from the specified metadata workspace,
    /// potentially rebinding and rebuilding the expressions to appropriate replacement metadata where necessary. 
    ///  
    internal class DbExpressionRebinder : DefaultExpressionVisitor
    { 
        private readonly MetadataWorkspace _metadata;
        private readonly Perspective _perspective;

        protected DbExpressionRebinder(MetadataWorkspace targetWorkspace) 
        {
            Debug.Assert(targetWorkspace != null, "Metadata workspace is null"); 
            _metadata = targetWorkspace; 
            _perspective = new ModelPerspective(targetWorkspace);
        } 

        //
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
        internal static DbExpression BindToWorkspace(DbExpression expression, MetadataWorkspace targetWorkspace) 
        {
            Debug.Assert(expression != null, "expression is null"); 
 
            DbExpressionRebinder copier = new DbExpressionRebinder(targetWorkspace);
            return copier.VisitExpression(expression); 
        }

        protected override EntitySetBase VisitEntitySet(EntitySetBase entitySet)
        { 
            EntityContainer container;
            if (_metadata.TryGetEntityContainer(entitySet.EntityContainer.Name, entitySet.EntityContainer.DataSpace, out container)) 
            { 
                EntitySetBase extent = null;
                if (container.BaseEntitySets.TryGetValue(entitySet.Name, false, out extent) && 
                    extent != null &&
                    entitySet.BuiltInTypeKind == extent.BuiltInTypeKind) // EntitySet -> EntitySet, AssociationSet -> AssociationSet, etc
                {
                    return extent; 
                }
 
                throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EntitySetNotFound(entitySet.EntityContainer.Name, entitySet.Name)); 
            }
 
            throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EntityContainerNotFound(entitySet.EntityContainer.Name));
        }

        protected override EdmFunction VisitFunction(EdmFunction function) 
        {
            List argumentTypes = new List(function.Parameters.Count); 
            foreach (FunctionParameter funcParam in function.Parameters) 
            {
                TypeUsage mappedParamType = this.VisitTypeUsage(funcParam.TypeUsage); 
                argumentTypes.Add(mappedParamType);
            }

            if (DataSpace.SSpace == function.DataSpace) 
            {
                EdmFunction foundFunc = null; 
                if (_metadata.TryGetFunction(function.Name, 
                                             function.NamespaceName,
                                             argumentTypes.ToArray(), 
                                             false /* ignoreCase */,
                                             function.DataSpace,
                                             out foundFunc) &&
                    foundFunc != null) 
                {
                    return foundFunc; 
                } 
            }
            else 
            {
                // find the function
                IList candidateFunctions;
                if (_perspective.TryGetFunctionByName(function.FullName, /*ignoreCase:*/ false, out candidateFunctions)) 
                {
                    Debug.Assert(null != candidateFunctions && candidateFunctions.Count > 0, "Perspective.TryGetFunctionByName returned true with null/empty function result list"); 
 
                    bool isAmbiguous;
                    EdmFunction retFunc = FunctionOverloadResolver.ResolveFunctionOverloads(candidateFunctions, argumentTypes, /*isGroupAggregateFunction:*/ false, out isAmbiguous); 
                    if (!isAmbiguous &&
                        retFunc != null)
                    {
                        return retFunc; 
                    }
                } 
            } 

            throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_FunctionNotFound(TypeHelpers.GetFullName(function))); 
        }

        protected override EdmType VisitType(EdmType type)
        { 
            EdmType retType = type;
 
            if (BuiltInTypeKind.RefType == type.BuiltInTypeKind) 
            {
                RefType refType = (RefType)type; 
                EntityType mappedEntityType = (EntityType)this.VisitType(refType.ElementType);
                if (!object.ReferenceEquals(refType.ElementType, mappedEntityType))
                {
                    retType = new RefType(mappedEntityType); 
                }
            } 
            else if (BuiltInTypeKind.CollectionType == type.BuiltInTypeKind) 
            {
                CollectionType collectionType = (CollectionType)type; 
                TypeUsage mappedElementType = this.VisitTypeUsage(collectionType.TypeUsage);
                if (!object.ReferenceEquals(collectionType.TypeUsage, mappedElementType))
                {
                    retType = new CollectionType(mappedElementType); 
                }
            } 
            else if (BuiltInTypeKind.RowType == type.BuiltInTypeKind) 
            {
                RowType rowType = (RowType)type; 
                List> mappedPropInfo = null;
                for (int idx = 0; idx < rowType.Properties.Count; idx++)
                {
                    EdmProperty originalProp = rowType.Properties[idx]; 
                    TypeUsage mappedPropType = this.VisitTypeUsage(originalProp.TypeUsage);
                    if (!object.ReferenceEquals(originalProp.TypeUsage, mappedPropType)) 
                    { 
                        if (mappedPropInfo == null)
                        { 
                            mappedPropInfo = new List>(
                                                rowType.Properties.Select(
                                                    prop => new KeyValuePair(prop.Name, prop.TypeUsage)
                                                )); 
                        }
                        mappedPropInfo[idx] = new KeyValuePair(originalProp.Name, mappedPropType); 
                    } 
                }
                if (mappedPropInfo != null) 
                {
                    IEnumerable mappedProps = mappedPropInfo.Select(propInfo => new EdmProperty(propInfo.Key, propInfo.Value));
                    retType = new RowType(mappedProps, rowType.InitializerMetadata);
                } 
            }
            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; 
        } 

        protected override TypeUsage VisitTypeUsage(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 = this.VisitType(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);
        } 

        private bool TryGetMember(DbExpression instance, string memberName, out TMember member) where TMember : EdmMember
        {
            member = null; 
            StructuralType declType = instance.ResultType.EdmType as StructuralType;
            if (declType != null) 
            { 
                EdmMember foundMember = null;
                if (declType.Members.TryGetValue(memberName, false, out foundMember)) 
                {
                    member = foundMember as TMember;
                }
            } 

            return (member != null); 
        } 

        public override DbExpression Visit(DbPropertyExpression expression) 
        {
            EntityUtil.CheckArgumentNull(expression, "expression");

            DbExpression result = expression; 
            DbExpression newInstance = this.VisitExpression(expression.Instance);
            if (!object.ReferenceEquals(expression.Instance, newInstance)) 
            { 
                if (Helper.IsRelationshipEndMember(expression.Property))
                { 
                    RelationshipEndMember endMember;
                    if(!TryGetMember(newInstance, expression.Property.Name, out endMember))
                    {
                        throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EndNotFound(expression.Property.Name, TypeHelpers.GetFullName(newInstance.ResultType.EdmType))); 
                    }
                    result = DbExpressionBuilder.Property(newInstance, endMember); 
                } 
                else if (Helper.IsNavigationProperty(expression.Property))
                { 
                    NavigationProperty navProp;
                    if (!TryGetMember(newInstance, expression.Property.Name, out navProp))
                    {
                        throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_NavPropertyNotFound(expression.Property.Name, TypeHelpers.GetFullName(newInstance.ResultType.EdmType))); 
                    }
                    result = DbExpressionBuilder.Property(newInstance, navProp); 
                } 
                else
                { 
                    EdmProperty prop;
                    if (!TryGetMember(newInstance, expression.Property.Name, out prop))
                    {
                        throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_PropertyNotFound(expression.Property.Name, TypeHelpers.GetFullName(newInstance.ResultType.EdmType))); 
                    }
                    result = DbExpressionBuilder.Property(newInstance, prop); 
                } 
            }
            return result; 
        }
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

using System; 
using System.Collections.Generic;
using System.Data.Common;
using System.Data.Metadata.Edm;
using System.Data.Common.CommandTrees; 
using System.Data.Common.CommandTrees.ExpressionBuilder;
using System.Diagnostics; 
using System.Globalization; 
using System.Linq;
using System.Data.Common.EntitySql; 

namespace System.Data.Common.CommandTrees.Internal
{
    ///  
    /// Ensures that all metadata in a given expression tree is from the specified metadata workspace,
    /// potentially rebinding and rebuilding the expressions to appropriate replacement metadata where necessary. 
    ///  
    internal class DbExpressionRebinder : DefaultExpressionVisitor
    { 
        private readonly MetadataWorkspace _metadata;
        private readonly Perspective _perspective;

        protected DbExpressionRebinder(MetadataWorkspace targetWorkspace) 
        {
            Debug.Assert(targetWorkspace != null, "Metadata workspace is null"); 
            _metadata = targetWorkspace; 
            _perspective = new ModelPerspective(targetWorkspace);
        } 

        //
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
        internal static DbExpression BindToWorkspace(DbExpression expression, MetadataWorkspace targetWorkspace) 
        {
            Debug.Assert(expression != null, "expression is null"); 
 
            DbExpressionRebinder copier = new DbExpressionRebinder(targetWorkspace);
            return copier.VisitExpression(expression); 
        }

        protected override EntitySetBase VisitEntitySet(EntitySetBase entitySet)
        { 
            EntityContainer container;
            if (_metadata.TryGetEntityContainer(entitySet.EntityContainer.Name, entitySet.EntityContainer.DataSpace, out container)) 
            { 
                EntitySetBase extent = null;
                if (container.BaseEntitySets.TryGetValue(entitySet.Name, false, out extent) && 
                    extent != null &&
                    entitySet.BuiltInTypeKind == extent.BuiltInTypeKind) // EntitySet -> EntitySet, AssociationSet -> AssociationSet, etc
                {
                    return extent; 
                }
 
                throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EntitySetNotFound(entitySet.EntityContainer.Name, entitySet.Name)); 
            }
 
            throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EntityContainerNotFound(entitySet.EntityContainer.Name));
        }

        protected override EdmFunction VisitFunction(EdmFunction function) 
        {
            List argumentTypes = new List(function.Parameters.Count); 
            foreach (FunctionParameter funcParam in function.Parameters) 
            {
                TypeUsage mappedParamType = this.VisitTypeUsage(funcParam.TypeUsage); 
                argumentTypes.Add(mappedParamType);
            }

            if (DataSpace.SSpace == function.DataSpace) 
            {
                EdmFunction foundFunc = null; 
                if (_metadata.TryGetFunction(function.Name, 
                                             function.NamespaceName,
                                             argumentTypes.ToArray(), 
                                             false /* ignoreCase */,
                                             function.DataSpace,
                                             out foundFunc) &&
                    foundFunc != null) 
                {
                    return foundFunc; 
                } 
            }
            else 
            {
                // find the function
                IList candidateFunctions;
                if (_perspective.TryGetFunctionByName(function.FullName, /*ignoreCase:*/ false, out candidateFunctions)) 
                {
                    Debug.Assert(null != candidateFunctions && candidateFunctions.Count > 0, "Perspective.TryGetFunctionByName returned true with null/empty function result list"); 
 
                    bool isAmbiguous;
                    EdmFunction retFunc = FunctionOverloadResolver.ResolveFunctionOverloads(candidateFunctions, argumentTypes, /*isGroupAggregateFunction:*/ false, out isAmbiguous); 
                    if (!isAmbiguous &&
                        retFunc != null)
                    {
                        return retFunc; 
                    }
                } 
            } 

            throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_FunctionNotFound(TypeHelpers.GetFullName(function))); 
        }

        protected override EdmType VisitType(EdmType type)
        { 
            EdmType retType = type;
 
            if (BuiltInTypeKind.RefType == type.BuiltInTypeKind) 
            {
                RefType refType = (RefType)type; 
                EntityType mappedEntityType = (EntityType)this.VisitType(refType.ElementType);
                if (!object.ReferenceEquals(refType.ElementType, mappedEntityType))
                {
                    retType = new RefType(mappedEntityType); 
                }
            } 
            else if (BuiltInTypeKind.CollectionType == type.BuiltInTypeKind) 
            {
                CollectionType collectionType = (CollectionType)type; 
                TypeUsage mappedElementType = this.VisitTypeUsage(collectionType.TypeUsage);
                if (!object.ReferenceEquals(collectionType.TypeUsage, mappedElementType))
                {
                    retType = new CollectionType(mappedElementType); 
                }
            } 
            else if (BuiltInTypeKind.RowType == type.BuiltInTypeKind) 
            {
                RowType rowType = (RowType)type; 
                List> mappedPropInfo = null;
                for (int idx = 0; idx < rowType.Properties.Count; idx++)
                {
                    EdmProperty originalProp = rowType.Properties[idx]; 
                    TypeUsage mappedPropType = this.VisitTypeUsage(originalProp.TypeUsage);
                    if (!object.ReferenceEquals(originalProp.TypeUsage, mappedPropType)) 
                    { 
                        if (mappedPropInfo == null)
                        { 
                            mappedPropInfo = new List>(
                                                rowType.Properties.Select(
                                                    prop => new KeyValuePair(prop.Name, prop.TypeUsage)
                                                )); 
                        }
                        mappedPropInfo[idx] = new KeyValuePair(originalProp.Name, mappedPropType); 
                    } 
                }
                if (mappedPropInfo != null) 
                {
                    IEnumerable mappedProps = mappedPropInfo.Select(propInfo => new EdmProperty(propInfo.Key, propInfo.Value));
                    retType = new RowType(mappedProps, rowType.InitializerMetadata);
                } 
            }
            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; 
        } 

        protected override TypeUsage VisitTypeUsage(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 = this.VisitType(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);
        } 

        private bool TryGetMember(DbExpression instance, string memberName, out TMember member) where TMember : EdmMember
        {
            member = null; 
            StructuralType declType = instance.ResultType.EdmType as StructuralType;
            if (declType != null) 
            { 
                EdmMember foundMember = null;
                if (declType.Members.TryGetValue(memberName, false, out foundMember)) 
                {
                    member = foundMember as TMember;
                }
            } 

            return (member != null); 
        } 

        public override DbExpression Visit(DbPropertyExpression expression) 
        {
            EntityUtil.CheckArgumentNull(expression, "expression");

            DbExpression result = expression; 
            DbExpression newInstance = this.VisitExpression(expression.Instance);
            if (!object.ReferenceEquals(expression.Instance, newInstance)) 
            { 
                if (Helper.IsRelationshipEndMember(expression.Property))
                { 
                    RelationshipEndMember endMember;
                    if(!TryGetMember(newInstance, expression.Property.Name, out endMember))
                    {
                        throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_EndNotFound(expression.Property.Name, TypeHelpers.GetFullName(newInstance.ResultType.EdmType))); 
                    }
                    result = DbExpressionBuilder.Property(newInstance, endMember); 
                } 
                else if (Helper.IsNavigationProperty(expression.Property))
                { 
                    NavigationProperty navProp;
                    if (!TryGetMember(newInstance, expression.Property.Name, out navProp))
                    {
                        throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_NavPropertyNotFound(expression.Property.Name, TypeHelpers.GetFullName(newInstance.ResultType.EdmType))); 
                    }
                    result = DbExpressionBuilder.Property(newInstance, navProp); 
                } 
                else
                { 
                    EdmProperty prop;
                    if (!TryGetMember(newInstance, expression.Property.Name, out prop))
                    {
                        throw EntityUtil.Argument(System.Data.Entity.Strings.Cqt_Copier_PropertyNotFound(expression.Property.Name, TypeHelpers.GetFullName(newInstance.ResultType.EdmType))); 
                    }
                    result = DbExpressionBuilder.Property(newInstance, prop); 
                } 
            }
            return result; 
        }
    }
}

// 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