File: System\Data\Common\Internal\Materialization\Translator.cs
Project: ndp\fx\src\DataEntity\System.Data.Entity.csproj (System.Data.Entity)
//------------------------------------------------------------------------------
// <copyright file="Translator.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
// <owner current="true" primary="true">Microsoft</owner>
// <owner current="true" primary="false">Microsoft</owner>
//------------------------------------------------------------------------------
 
namespace System.Data.Common.Internal.Materialization
{
    using System.Collections.Generic;
    using System.Data;
    using System.Data.Common.QueryCache;
    using System.Data.Common.Utils;
    using System.Data.Entity;
    using System.Data.Mapping;
    using System.Data.Metadata.Edm;
    using System.Data.Objects;
    using System.Data.Objects.DataClasses;
    using System.Data.Objects.ELinq;
    using System.Data.Objects.Internal;
    using System.Data.Query.InternalTrees;
    using System.Diagnostics;
    using System.Globalization;
    using System.Linq.Expressions;
    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.Security.Permissions;
 
    /// <summary>
    /// Struct containing the requested type and parent column map used
    /// as the arg in the Translator visitor.
    /// </summary>
    internal struct TranslatorArg
    {
        internal readonly Type RequestedType;
 
        internal TranslatorArg(Type requestedType)
        {
            this.RequestedType = requestedType;
        }
    }
 
    /// <summary>
    /// Type returned by the Translator visitor; allows us to put the logic
    /// to ensure a specific return type in a single place, instead of in 
    /// each Visit method.
    /// </summary>
    internal class TranslatorResult
    {
        private readonly Expression ReturnedExpression;
        private readonly Type RequestedType;
 
        internal TranslatorResult(Expression returnedExpression, Type requestedType)
        {
            this.RequestedType = requestedType;
            this.ReturnedExpression = returnedExpression;
        }
 
        /// <summary>
        /// Return the expression; wrapped with the appropriate cast/convert
        /// logic to guarantee it's type.
        /// </summary>
        internal Expression Expression
        {
            get
            {
                Expression result = Translator.Emit_EnsureType(ReturnedExpression, RequestedType);
                return result;
            }
        }
 
        /// <summary>
        /// Return the expression without attempting to cast/convert to the requested type.
        /// </summary>
        internal Expression UnconvertedExpression
        {
            get
            {
                return ReturnedExpression;
            }
        }
 
        /// <summary>
        /// Checks if the expression represents an wrapped entity and if so creates an expression
        /// that extracts the raw entity from the wrapper.
        /// </summary>
        internal Expression UnwrappedExpression
        {
            get
            {
                if (!typeof(IEntityWrapper).IsAssignableFrom(ReturnedExpression.Type))
                {
                    return ReturnedExpression;
                }
                return Translator.Emit_UnwrapAndEnsureType(ReturnedExpression, RequestedType);
            }
        }
    }
 
    /// <summary>
    /// For collection results, we really want to know the expression to
    /// get the coordinator from its stateslot as well, so we have an 
    /// additional one...
    /// </summary>
    internal class CollectionTranslatorResult : TranslatorResult
    {
        internal readonly Expression ExpressionToGetCoordinator;
 
        internal CollectionTranslatorResult(Expression returnedExpression, ColumnMap columnMap, Type requestedType, Expression expressionToGetCoordinator)
            : base(returnedExpression, requestedType)
        {
            this.ExpressionToGetCoordinator = expressionToGetCoordinator;
        }
    }
 
    /// <summary>
    /// Translates query ColumnMap into ShaperFactory. Basically, we interpret the 
    /// ColumnMap and compile delegates used to materialize results.
    /// </summary>
    internal class Translator : ColumnMapVisitorWithResults<TranslatorResult, TranslatorArg>
    {
        #region private state
 
        /// <summary>
        /// Gets the O-Space Metadata workspace.
        /// </summary>
        private readonly MetadataWorkspace _workspace;
 
        /// <summary>
        /// Gets structure telling us how to interpret 'span' rows (includes implicit
        /// relationship span and explicit full span via ObjectQuery.Include().
        /// </summary>
        private readonly SpanIndex _spanIndex;
 
        /// <summary>
        /// Gets the MergeOption for the current query (influences our handling of 
        /// entities when they are materialized).
        /// </summary>
        private readonly MergeOption _mergeOption;
 
        /// <summary>
        /// When true, indicates we're processing for the value layer (BridgeDataReader)
        /// and not the ObjectMaterializer
        /// </summary>
        private readonly bool IsValueLayer;
 
        /// <summary>
        /// Gets scratchpad for topmost nested reader coordinator.
        /// </summary>
        private CoordinatorScratchpad _rootCoordinatorScratchpad;
 
        /// <summary>
        /// Gets scratchpad for the coordinator builder for the nested reader currently
        /// being translated or emitted.
        /// </summary>
        private CoordinatorScratchpad _currentCoordinatorScratchpad;
 
        /// <summary>
        /// Gets number of 'Shaper.State' slots allocated (used to hold onto intermediate
        /// values during materialization)
        /// </summary>
        private int _stateSlotCount;
 
        /// <summary>
        /// Set to true if any Entity/Complex type/property for which we're emitting a
        /// handler is non-public. Used to determine which security checks are necessary 
        /// when invoking the delegate.
        /// </summary>
        private bool _hasNonPublicMembers;
 
        /// <summary>
        /// Local cache of ObjectTypeMappings for EdmTypes (to prevent expensive lookups).
        /// </summary>
        private readonly Dictionary<EdmType, ObjectTypeMapping> _objectTypeMappings = new Dictionary<EdmType, ObjectTypeMapping>();
 
        #endregion
 
        #region constructor
 
        private Translator(MetadataWorkspace workspace, SpanIndex spanIndex, MergeOption mergeOption, bool valueLayer)
        {
            _workspace = workspace;
            _spanIndex = spanIndex;
            _mergeOption = mergeOption;
            IsValueLayer = valueLayer;
        }
 
        #endregion
 
        #region "public" surface area
 
        /// <summary>
        /// The main entry point for the translation process. Given a ColumnMap, returns 
        /// a ShaperFactory which can be used to materialize results for a query.
        /// </summary>
        internal static ShaperFactory<TRequestedType> TranslateColumnMap<TRequestedType>(QueryCacheManager queryCacheManager, ColumnMap columnMap, MetadataWorkspace workspace, SpanIndex spanIndex, MergeOption mergeOption, bool valueLayer)
        {
            Debug.Assert(columnMap is CollectionColumnMap, "root column map must be a collection for a query");
 
            // If the query cache already contains a plan, then we're done
            ShaperFactory<TRequestedType> result;
            string columnMapKey = ColumnMapKeyBuilder.GetColumnMapKey(columnMap, spanIndex);
            ShaperFactoryQueryCacheKey<TRequestedType> cacheKey = new ShaperFactoryQueryCacheKey<TRequestedType>(columnMapKey, mergeOption, valueLayer);
 
            if (queryCacheManager.TryCacheLookup<ShaperFactoryQueryCacheKey<TRequestedType>, ShaperFactory<TRequestedType>>(cacheKey, out result))
            {
                return result;
            }
 
            // Didn't find it in the cache, so we have to do the translation;  First create
            // the translator visitor that recursively tranforms ColumnMaps into Expressions
            // stored on the CoordinatorScratchpads it also constructs.  We'll compile those
            // expressions into delegates later.
            Translator translator = new Translator(workspace, spanIndex, mergeOption, valueLayer);
            columnMap.Accept(translator, new TranslatorArg(typeof(IEnumerable<>).MakeGenericType(typeof(TRequestedType))));
 
            Debug.Assert(null != translator._rootCoordinatorScratchpad, "translating the root of the query must populate _rootCoordinatorBuilder"); // how can this happen?
 
            // We're good. Go ahead and recursively compile the CoordinatorScratchpads we
            // created in the vistor into CoordinatorFactories which contain compiled
            // delegates for the expressions we generated.
            CoordinatorFactory<TRequestedType> coordinatorFactory = (CoordinatorFactory<TRequestedType>)translator._rootCoordinatorScratchpad.Compile();
 
            // Along the way we constructed a nice delegate to perform runtime permission 
            // checks (e.g. for LinkDemand and non-public members).  We need that now.
            Action checkPermissionsDelegate = translator.GetCheckPermissionsDelegate();
 
            // Finally, take everything we've produced, and create the ShaperFactory to
            // contain it all, then add it to the query cache so we don't need to do this
            // for this query again.
            result = new ShaperFactory<TRequestedType>(translator._stateSlotCount, coordinatorFactory, checkPermissionsDelegate, mergeOption);
            QueryCacheEntry cacheEntry = new QueryCacheEntry(cacheKey, result);
            if (queryCacheManager.TryLookupAndAdd(cacheEntry, out cacheEntry))
            {
                // Someone beat us to it. Use their result instead.
                result = (ShaperFactory<TRequestedType>)cacheEntry.GetTarget();
            }
            return result;
        }
 
        /// <summary>
        /// Compiles a delegate taking a Shaper instance and returning values. Used to compile 
        /// Expressions produced by the emitter.
        /// 
        /// Asserts MemberAccess to skip visbility check.  
        /// This means that that security checks are skipped. Before calling this
        /// method you must ensure that you've done a TestComple on expressions provided
        /// by the user to ensure the compilation doesn't violate them.
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2128")]
        [System.Security.SecuritySafeCritical]
        [ReflectionPermission(SecurityAction.Assert, MemberAccess = true)]
        internal static Func<Shaper, TResult> Compile<TResult>(Expression body)
        {
            var lambda = Expression.Lambda<Func<Shaper, TResult>>(body, Shaper_Parameter);
            return lambda.Compile();
        }
 
        /// <summary>
        /// Non-generic version of Compile (where the result type is passed in as an argument rather
        /// than a type parameter)
        /// </summary>
        [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
        internal static object Compile(Type resultType, Expression body)
        {
            MethodInfo compile = Translator_Compile.MakeGenericMethod(resultType);
            return compile.Invoke(null, new object[] { body });
        }
 
        #endregion
 
        #region helpers
 
        /// <summary>
        /// Allocates a slot in 'Shaper.State' which can be used as storage for 
        /// materialization tasks (e.g. remembering key values for a nested collection)
        /// </summary>
        private int AllocateStateSlot()
        {
            return _stateSlotCount++;
        }
 
        /// <summary>
        /// Returns a delegate performing necessary permission checks identified
        /// by this translator.  This delegate must be called every time a row is 
        /// read from the ObjectResult enumerator, since the enumerator can be 
        /// passed across security contexts.
        /// </summary>
        private Action GetCheckPermissionsDelegate()
        {
            // Emit an action to check runtime permissions.
            return _hasNonPublicMembers ? (Action)DemandMemberAccess : null;
        }
 
        private static void DemandMemberAccess()
        {
            LightweightCodeGenerator.MemberAccessReflectionPermission.Demand();
        }
 
        /// <summary>
        /// Try compiling the user expressions to ensure it would succeed without an 
        /// assert (user expressions are inlined with references to EF internals which 
        /// require the assert so we need to check the user expressions separately).
        /// 
        /// This method is called every time a new query result is returned to make sure
        /// the user expressions can be compiled in the current security context.
        /// </summary>
        private static void VerifyUserExpressions(IEnumerable<Expression<Func<object>>> userExpressions)
        {
            // As an optimization, check if we have member access permission. If so,
            // we know the compile would succeed and don't need to make the effort.
            if (!LightweightCodeGenerator.HasMemberAccessReflectionPermission())
            {
                // If we don't have MemberAccess, compile the expressions to see if they
                // might be satisfied by RestrictedMemberAccess.
                foreach (Expression<Func<object>> userExpression in userExpressions)
                {
                    userExpression.Compile();
                }
            }
        }
 
        /// <summary>
        /// Return the CLR type we're supposed to materialize for the TypeUsage
        /// </summary>
        private Type DetermineClrType(TypeUsage typeUsage)
        {
            return DetermineClrType(typeUsage.EdmType);
        }
 
        /// <summary>
        /// Return the CLR type we're supposed to materialize for the EdmType
        /// </summary>
        private Type DetermineClrType(EdmType edmType)
        {
            Type result = null;
            // Normalize for spandex
            edmType = ResolveSpanType(edmType);
 
            switch (edmType.BuiltInTypeKind)
            {
                case BuiltInTypeKind.EntityType:
                case BuiltInTypeKind.ComplexType:
                    if (IsValueLayer)
                    {
                        result = typeof(RecordState);
                    }
                    else
                    {
                        result = LookupObjectMapping(edmType).ClrType.ClrType;
                    }
                    break;
 
                case BuiltInTypeKind.RefType:
                    result = typeof(EntityKey);
                    break;
 
                case BuiltInTypeKind.CollectionType:
                    if (IsValueLayer)
                    {
                        result = typeof(Coordinator<RecordState>);
                    }
                    else
                    {
                        EdmType edmElementType = ((CollectionType)edmType).TypeUsage.EdmType;
                        result = DetermineClrType(edmElementType);
                        result = typeof(IEnumerable<>).MakeGenericType(result);
                    }
                    break;
 
                case BuiltInTypeKind.EnumType:
                    if (IsValueLayer)
                    {
                        result = DetermineClrType(((EnumType)edmType).UnderlyingType);
                    }
                    else
                    {
                        result = LookupObjectMapping(edmType).ClrType.ClrType;
                        result = typeof(Nullable<>).MakeGenericType(result);
                    }
                    break;
 
                case BuiltInTypeKind.PrimitiveType:
                    result = ((PrimitiveType)edmType).ClrEquivalentType;
                    if (result.IsValueType)
                    {
                        result = typeof(Nullable<>).MakeGenericType(result);
                    }
                    break;
 
                case BuiltInTypeKind.RowType:
                    if (IsValueLayer)
                    {
                        result = typeof(RecordState);
                    }
                    else
                    {
                        // LINQ has anonymous types that aren't going to show up in our
                        // metadata workspace, and we don't want to hydrate a record when
                        // we need an anonymous type.  ELINQ solves this by annotating the
                        // edmType with some additional information, which we'll pick up 
                        // here.
                        InitializerMetadata initializerMetadata = ((RowType)edmType).InitializerMetadata;
                        if (null != initializerMetadata)
                        {
                            result = initializerMetadata.ClrType;
                        }
                        else
                        {
                            // Otherwise, by default, we'll give DbDataRecord results (the 
                            // user can also cast to IExtendedDataRecord)
                            result = typeof(DbDataRecord);
                        }
                    }
                    break;
 
                default:
                    Debug.Fail(string.Format(CultureInfo.CurrentCulture, "The type {0} was not the expected scalar, enumeration, collection, structural, nominal, or reference type.", edmType.GetType()));
                    break;
            }
            Debug.Assert(null != result, "no result?"); // just making sure we cover this in the switch statement.
 
            return result;
        }
 
        /// <summary>
        /// Get the ConstructorInfo for the type specified, and ensure we keep track
        /// of any security requirements that the type has.
        /// </summary>
        private ConstructorInfo GetConstructor(Type type)
        {
            ConstructorInfo result = null;
            if (!type.IsAbstract)
            {
                result = LightweightCodeGenerator.GetConstructorForType(type);
 
                // remember security requirements for this constructor
                if (!LightweightCodeGenerator.IsPublic(result))
                {
                    _hasNonPublicMembers = true;
                }
            }
            return result;
        }
 
        /// <summary>
        /// Retrieves object mapping metadata for the given type. The first time a type 
        /// is encountered, we cache the metadata to avoid repeating the work for every 
        /// row in result. 
        /// 
        /// Caching at the materializer rather than workspace/metadata cache level optimizes
        /// for transient types (including row types produced for span, LINQ initializations, 
        /// collections and projections).
        /// </summary>
        private ObjectTypeMapping LookupObjectMapping(EdmType edmType)
        {
            Debug.Assert(null != edmType, "no edmType?"); // edmType must not be null.
 
            ObjectTypeMapping result;
 
            EdmType resolvedType = ResolveSpanType(edmType);
            if (null == resolvedType)
            {
                resolvedType = edmType;
            }
 
            if (!_objectTypeMappings.TryGetValue(resolvedType, out result))
            {
                result = Util.GetObjectMapping(resolvedType, _workspace);
                _objectTypeMappings.Add(resolvedType, result);
            }
            return result;
        }
 
        /// <summary>
        /// Remove spanned info from the edmType
        /// </summary>
        /// <param name="edmType"></param>
        /// <returns></returns>
        private EdmType ResolveSpanType(EdmType edmType)
        {
            EdmType result = edmType;
 
            switch (result.BuiltInTypeKind)
            {
                case BuiltInTypeKind.CollectionType:
                    // For collections, we have to edmType from the (potentially) spanned
                    // element of the collection, then build a new Collection around it.
                    result = ResolveSpanType(((CollectionType)result).TypeUsage.EdmType);
                    if (null != result)
                    {
                        result = new CollectionType(result);
                    }
                    break;
 
                case BuiltInTypeKind.RowType:
                    // If there is a SpanMap, pick up the EdmType from the first column
                    // in the record, otherwise it's just the type we already have.
                    RowType rowType = (RowType)result;
                    if (null != _spanIndex && _spanIndex.HasSpanMap(rowType))
                    {
                        result = rowType.Members[0].TypeUsage.EdmType;
                    }
                    break;
            }
            return result;
        }
 
        /// <summary>
        /// Creates an expression representing an inline delegate of type Func&lt;Shaper, body.Type&gt;
        /// </summary>
        [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
        private LambdaExpression CreateInlineDelegate(Expression body)
        {
            // Note that we call through to a typed method so that we can call Expression.Lambda<Func> instead
            // of the straightforward Expression.Lambda. The latter requires FullTrust.
            Type delegateReturnType = body.Type;
            MethodInfo createMethod = Translator_TypedCreateInlineDelegate.MakeGenericMethod(delegateReturnType);
            LambdaExpression result = (LambdaExpression)createMethod.Invoke(this, new object[] { body });
            return result;
        }
 
        private Expression<Func<Shaper, T>> TypedCreateInlineDelegate<T>(Expression body)
        {
            Expression<Func<Shaper, T>> result = Expression.Lambda<Func<Shaper, T>>(body, Shaper_Parameter);
            _currentCoordinatorScratchpad.AddInlineDelegate(result);
            return result;
        }
 
        #endregion
 
        #region Lightweight CodeGen emitters
 
        #region static Reflection info used in emitters
 
        private static readonly MethodInfo DbDataReader_GetValue = typeof(DbDataReader).GetMethod("GetValue");
        private static readonly MethodInfo DbDataReader_GetString = typeof(DbDataReader).GetMethod("GetString");
        private static readonly MethodInfo DbDataReader_GetInt16 = typeof(DbDataReader).GetMethod("GetInt16");
        private static readonly MethodInfo DbDataReader_GetInt32 = typeof(DbDataReader).GetMethod("GetInt32");
        private static readonly MethodInfo DbDataReader_GetInt64 = typeof(DbDataReader).GetMethod("GetInt64");
        private static readonly MethodInfo DbDataReader_GetBoolean = typeof(DbDataReader).GetMethod("GetBoolean");
        private static readonly MethodInfo DbDataReader_GetDecimal = typeof(DbDataReader).GetMethod("GetDecimal");
        private static readonly MethodInfo DbDataReader_GetFloat = typeof(DbDataReader).GetMethod("GetFloat");
        private static readonly MethodInfo DbDataReader_GetDouble = typeof(DbDataReader).GetMethod("GetDouble");
        private static readonly MethodInfo DbDataReader_GetDateTime = typeof(DbDataReader).GetMethod("GetDateTime");
        private static readonly MethodInfo DbDataReader_GetGuid = typeof(DbDataReader).GetMethod("GetGuid");
        private static readonly MethodInfo DbDataReader_GetByte = typeof(DbDataReader).GetMethod("GetByte");
        private static readonly MethodInfo DbDataReader_IsDBNull = typeof(DbDataReader).GetMethod("IsDBNull");
 
        private static readonly ConstructorInfo EntityKey_ctor_SingleKey = typeof(EntityKey).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(EntitySet), typeof(object) }, null);
        private static readonly ConstructorInfo EntityKey_ctor_CompositeKey = typeof(EntityKey).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(EntitySet), typeof(object[]) }, null);
 
        private static readonly MethodInfo IEntityKeyWithKey_EntityKey = typeof(System.Data.Objects.DataClasses.IEntityWithKey).GetProperty("EntityKey").GetSetMethod();
 
        private static readonly MethodInfo IEqualityComparerOfString_Equals = typeof(IEqualityComparer<String>).GetMethod("Equals", new Type[] { typeof(string), typeof(string) });
 
        private static readonly ConstructorInfo MaterializedDataRecord_ctor = typeof(MaterializedDataRecord).GetConstructor(
                                                                                            BindingFlags.NonPublic | BindingFlags.Instance,
                                                                                            null, new Type[] { typeof(MetadataWorkspace), typeof(TypeUsage), typeof(object[]) },
                                                                                            null);
 
        private static readonly MethodInfo RecordState_GatherData = typeof(RecordState).GetMethod("GatherData", BindingFlags.NonPublic | BindingFlags.Instance);
        private static readonly MethodInfo RecordState_SetNullRecord = typeof(RecordState).GetMethod("SetNullRecord", BindingFlags.NonPublic | BindingFlags.Instance);
 
        private static readonly MethodInfo Shaper_Discriminate = typeof(Shaper).GetMethod("Discriminate");
        private static readonly MethodInfo Shaper_GetPropertyValueWithErrorHandling = typeof(Shaper).GetMethod("GetPropertyValueWithErrorHandling");
        private static readonly MethodInfo Shaper_GetColumnValueWithErrorHandling = typeof(Shaper).GetMethod("GetColumnValueWithErrorHandling");
        private static readonly MethodInfo Shaper_GetGeographyColumnValue = typeof(Shaper).GetMethod("GetGeographyColumnValue");
        private static readonly MethodInfo Shaper_GetGeometryColumnValue = typeof(Shaper).GetMethod("GetGeometryColumnValue");
        private static readonly MethodInfo Shaper_GetSpatialColumnValueWithErrorHandling = typeof(Shaper).GetMethod("GetSpatialColumnValueWithErrorHandling");
        private static readonly MethodInfo Shaper_GetSpatialPropertyValueWithErrorHandling = typeof(Shaper).GetMethod("GetSpatialPropertyValueWithErrorHandling");
        private static readonly MethodInfo Shaper_HandleEntity = typeof(Shaper).GetMethod("HandleEntity");
        private static readonly MethodInfo Shaper_HandleEntityAppendOnly = typeof(Shaper).GetMethod("HandleEntityAppendOnly");
        private static readonly MethodInfo Shaper_HandleEntityNoTracking = typeof(Shaper).GetMethod("HandleEntityNoTracking");
        private static readonly MethodInfo Shaper_HandleFullSpanCollection = typeof(Shaper).GetMethod("HandleFullSpanCollection");
        private static readonly MethodInfo Shaper_HandleFullSpanElement = typeof(Shaper).GetMethod("HandleFullSpanElement");
        private static readonly MethodInfo Shaper_HandleIEntityWithKey = typeof(Shaper).GetMethod("HandleIEntityWithKey");
        private static readonly MethodInfo Shaper_HandleRelationshipSpan = typeof(Shaper).GetMethod("HandleRelationshipSpan");
        private static readonly MethodInfo Shaper_SetColumnValue = typeof(Shaper).GetMethod("SetColumnValue");
        private static readonly MethodInfo Shaper_SetEntityRecordInfo = typeof(Shaper).GetMethod("SetEntityRecordInfo");
        private static readonly MethodInfo Shaper_SetState = typeof(Shaper).GetMethod("SetState");
        private static readonly MethodInfo Shaper_SetStatePassthrough = typeof(Shaper).GetMethod("SetStatePassthrough");
 
        private static readonly MethodInfo Translator_BinaryEquals = typeof(Translator).GetMethod("BinaryEquals", BindingFlags.NonPublic | BindingFlags.Static);
        private static readonly MethodInfo Translator_CheckedConvert = typeof(Translator).GetMethod("CheckedConvert", BindingFlags.NonPublic | BindingFlags.Static);
        private static readonly MethodInfo Translator_Compile = typeof(Translator).GetMethod("Compile", BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof(Expression) }, null);
        private static readonly MethodInfo Translator_MultipleDiscriminatorPolymorphicColumnMapHelper = typeof(Translator).GetMethod("MultipleDiscriminatorPolymorphicColumnMapHelper", BindingFlags.NonPublic | BindingFlags.Instance);
        private static readonly MethodInfo Translator_TypedCreateInlineDelegate = typeof(Translator).GetMethod("TypedCreateInlineDelegate", BindingFlags.NonPublic | BindingFlags.Instance);
 
        private static readonly PropertyInfo EntityWrapperFactory_NullWrapper = typeof(EntityWrapperFactory).GetProperty("NullWrapper", BindingFlags.Static | BindingFlags.NonPublic);
        private static readonly PropertyInfo IEntityWrapper_Entity = typeof(IEntityWrapper).GetProperty("Entity");
        private static readonly MethodInfo EntityProxyTypeInfo_SetEntityWrapper = typeof(EntityProxyTypeInfo).GetMethod("SetEntityWrapper", BindingFlags.NonPublic | BindingFlags.Instance);
 
        private static readonly ConstructorInfo PocoPropertyAccessorStrategy_ctor = typeof(PocoPropertyAccessorStrategy).GetConstructor(new Type[] { typeof(object) });
        private static readonly ConstructorInfo EntityWithChangeTrackerStrategy_ctor = typeof(EntityWithChangeTrackerStrategy).GetConstructor(new Type[] { typeof(IEntityWithChangeTracker) });
        private static readonly ConstructorInfo EntityWithKeyStrategy_ctor = typeof(EntityWithKeyStrategy).GetConstructor(new Type[] { typeof(IEntityWithKey) });
        private static readonly ConstructorInfo PocoEntityKeyStrategy_ctor = typeof(PocoEntityKeyStrategy).GetConstructor(new Type[0]);
        private static readonly PropertyInfo SnapshotChangeTrackingStrategy_Instance = typeof(SnapshotChangeTrackingStrategy).GetProperty("Instance", BindingFlags.Static | BindingFlags.Public);
 
        private static readonly MethodInfo EntityWrapperFactory_GetPocoPropertyAccessorStrategyFunc = typeof(EntityWrapperFactory).GetMethod("GetPocoPropertyAccessorStrategyFunc", BindingFlags.NonPublic | BindingFlags.Static);
        private static readonly MethodInfo EntityWrapperFactory_GetNullPropertyAccessorStrategyFunc = typeof(EntityWrapperFactory).GetMethod("GetNullPropertyAccessorStrategyFunc", BindingFlags.NonPublic | BindingFlags.Static);
        private static readonly MethodInfo EntityWrapperFactory_GetEntityWithChangeTrackerStrategyFunc = typeof(EntityWrapperFactory).GetMethod("GetEntityWithChangeTrackerStrategyFunc", BindingFlags.NonPublic | BindingFlags.Static);
        private static readonly MethodInfo EntityWrapperFactory_GetSnapshotChangeTrackingStrategyFunc = typeof(EntityWrapperFactory).GetMethod("GetSnapshotChangeTrackingStrategyFunc", BindingFlags.NonPublic | BindingFlags.Static);
        private static readonly MethodInfo EntityWrapperFactory_GetEntityWithKeyStrategyStrategyFunc = typeof(EntityWrapperFactory).GetMethod("GetEntityWithKeyStrategyStrategyFunc", BindingFlags.NonPublic | BindingFlags.Static);
        private static readonly MethodInfo EntityWrapperFactory_GetPocoEntityKeyStrategyFunc = typeof(EntityWrapperFactory).GetMethod("GetPocoEntityKeyStrategyFunc", BindingFlags.NonPublic | BindingFlags.Static);
 
        #endregion
 
        #region static expressions used in emitters
 
        private static readonly Expression DBNull_Value = Expression.Constant(DBNull.Value, typeof(object));
 
        internal static readonly ParameterExpression Shaper_Parameter = Expression.Parameter(typeof(Shaper), "shaper");
        private static readonly ParameterExpression EntityParameter = Expression.Parameter(typeof(object), "entity");
 
        internal static readonly Expression Shaper_Reader = Expression.Field(Shaper_Parameter, typeof(Shaper).GetField("Reader"));
        private static readonly Expression Shaper_Workspace = Expression.Field(Shaper_Parameter, typeof(Shaper).GetField("Workspace"));
        private static readonly Expression Shaper_State = Expression.Field(Shaper_Parameter, typeof(Shaper).GetField("State"));
        private static readonly Expression Shaper_Context = Expression.Field(Shaper_Parameter, typeof(Shaper).GetField("Context"));
        private static readonly Expression Shaper_Context_Options = Expression.Property(Shaper_Context, typeof(ObjectContext).GetProperty("ContextOptions"));
        private static readonly Expression Shaper_ProxyCreationEnabled = Expression.Property(Shaper_Context_Options, typeof(ObjectContextOptions).GetProperty("ProxyCreationEnabled"));
 
        #endregion
 
        /// <summary>
        /// Create expression to AndAlso the expressions and return the result.
        /// </summary>
        private static Expression Emit_AndAlso(IEnumerable<Expression> operands)
        {
            Expression result = null;
            foreach (Expression operand in operands)
            {
                if (result == null)
                {
                    result = operand;
                }
                else
                {
                    result = Expression.AndAlso(result, operand);
                }
            }
            return result;
        }
 
        /// <summary>
        /// Create expression to bitwise-or the expressions and return the result.
        /// </summary>
        private static Expression Emit_BitwiseOr(IEnumerable<Expression> operands)
        {
            Expression result = null;
            foreach (Expression operand in operands)
            {
                if (result == null)
                {
                    result = operand;
                }
                else
                {
                    result = Expression.Or(result, operand);
                }
            }
            return result;
        }
 
        /// <summary>
        /// Creates an expression with null value. If the given type cannot be assigned
        /// a null value, we create a value that throws when materializing. We don't throw statically
        /// because we consistently defer type checks until materialization.
        /// 
        /// See SQL BU 588980.
        /// </summary>
        /// <param name="type">Type of null expression.</param>
        /// <returns>Null expression.</returns>
        internal static Expression Emit_NullConstant(Type type)
        {
            Expression nullConstant;
            EntityUtil.CheckArgumentNull(type, "type");
 
            // check if null can be assigned to the type
            if (type.IsClass || TypeSystem.IsNullableType(type))
            {
                // create the constant directly if it accepts null
                nullConstant = Expression.Constant(null, type);
            }
            else
            {
                // create (object)null and then cast to the type
                nullConstant = Emit_EnsureType(Expression.Constant(null, typeof(object)), type);
            }
            return nullConstant;
        }
 
        /// <summary>
        /// Emits an expression that represnts a NullEntityWrapper instance.
        /// </summary>
        /// <param name="type">The type of the null to be wrapped</param>
        /// <returns>An expression represnting a wrapped null</returns>
        internal static Expression Emit_WrappedNullConstant(Type type)
        {
            return Expression.Property(null, EntityWrapperFactory_NullWrapper);
        }
 
        /// <summary>
        /// Create expression that guarantees the input expression is of the specified
        /// type; no Convert is added if the expression is already of the same type.
        /// 
        /// Internal because it is called from the TranslatorResult.
        /// </summary>
        internal static Expression Emit_EnsureType(Expression input, Type type)
        {
            Expression result = input;
            if (input.Type != type && !typeof(IEntityWrapper).IsAssignableFrom(input.Type))
            {
                if (type.IsAssignableFrom(input.Type))
                {
                    // simple convert, just to make sure static type checks succeed
                    result = Expression.Convert(input, type);
                }
                else
                {
                    // user is asking for the 'wrong' type... add exception handling
                    // in case of failure
                    MethodInfo checkedConvertMethod = Translator_CheckedConvert.MakeGenericMethod(input.Type, type);
                    result = Expression.Call(checkedConvertMethod, input);
                }
            }
            return result;
        }
 
        /// <summary>
        /// Uses Emit_EnsureType and then wraps the result in an IEntityWrapper instance.
        /// </summary>
        /// <param name="input">The expression that creates the entity to be wrapped</param>
        /// <param name="keyReader">Expression to read the entity key</param>
        /// <param name="entitySetReader">Expression to read the entity set</param>
        /// <param name="requestedType">The type that was actuall requested by the client--may be object</param>
        /// <param name="identityType">The type of the identity type of the entity being materialized--never a proxy type</param>
        /// <param name="actualType">The actual type being materialized--may be a proxy type</param>
        /// <param name="mergeOption">Either NoTracking or AppendOnly depending on whether the entity is to be tracked</param>
        /// <param name="isProxy">If true, then a proxy is being created</param>
        /// <returns>An expression representing the IEntityWrapper for the new entity</returns>
        internal static Expression Emit_EnsureTypeAndWrap(Expression input, Expression keyReader, Expression entitySetReader, Type requestedType, Type identityType, Type actualType, MergeOption mergeOption, bool isProxy)
        {
            Expression result = Emit_EnsureType(input, requestedType); // Needed to ensure appropriate exception is thrown
            if (!requestedType.IsClass)
            {
                result = Emit_EnsureType(input, typeof(object));
            }
            result = Emit_EnsureType(result, actualType); // Needed to ensure appropriate type for wrapper constructor
            return CreateEntityWrapper(result, keyReader, entitySetReader, actualType, identityType, mergeOption, isProxy);
        }
 
        /// <summary>
        /// Returns an expression that creates an IEntityWrapper approprioate for the type of entity being materialized.
        /// </summary>
        private static Expression CreateEntityWrapper(Expression input, Expression keyReader, Expression entitySetReader, Type actualType, Type identityType, MergeOption mergeOption, bool isProxy)
        {
            Expression result;
            bool isIEntityWithKey = typeof(IEntityWithKey).IsAssignableFrom(actualType);
            bool isIEntityWithRelationships = typeof(IEntityWithRelationships).IsAssignableFrom(actualType);
            bool isIEntityWithChangeTracker = typeof(IEntityWithChangeTracker).IsAssignableFrom(actualType);
            if (isIEntityWithRelationships && isIEntityWithChangeTracker && isIEntityWithKey && !isProxy)
            {
                // This is the case where all our interfaces are implemented by the entity and we are not creating a proxy.
                // This is the case that absolutely must be kept fast.  It is a simple call to the wrapper constructor.
                Type genericType = typeof(LightweightEntityWrapper<>).MakeGenericType(actualType);
                ConstructorInfo ci = genericType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.CreateInstance, null,
                                                                new Type[] { actualType, typeof(EntityKey), typeof(EntitySet), typeof(ObjectContext), typeof(MergeOption), typeof(Type) }, null);
                result = Expression.New(ci, input, keyReader, entitySetReader, Shaper_Context, Expression.Constant(mergeOption, typeof(MergeOption)), Expression.Constant(identityType, typeof(Type)));
            }
            else
            {
                // This is the general case.  We choose various strategy objects based on the interfaces implemented and
                // whether or not we are creating a proxy.
                // We pass in lambdas to create the strategy objects so that they can have the materialized entity as
                // a parameter while still being set in the wrapper constructor.
                Expression propertyAccessorStrategy = !isIEntityWithRelationships || isProxy ?
                                                      Expression.Call(EntityWrapperFactory_GetPocoPropertyAccessorStrategyFunc) :
                                                      Expression.Call(EntityWrapperFactory_GetNullPropertyAccessorStrategyFunc);
 
                Expression keyStrategy = isIEntityWithKey ?
                                         Expression.Call(EntityWrapperFactory_GetEntityWithKeyStrategyStrategyFunc) :
                                         Expression.Call(EntityWrapperFactory_GetPocoEntityKeyStrategyFunc);
 
                Expression changeTrackingStrategy = isIEntityWithChangeTracker ?
                                                    Expression.Call(EntityWrapperFactory_GetEntityWithChangeTrackerStrategyFunc) :
                                                    Expression.Call(EntityWrapperFactory_GetSnapshotChangeTrackingStrategyFunc);
 
                Type genericType = isIEntityWithRelationships ?
                                   typeof(EntityWrapperWithRelationships<>).MakeGenericType(actualType) :
                                   typeof(EntityWrapperWithoutRelationships<>).MakeGenericType(actualType);
 
                ConstructorInfo ci = genericType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.CreateInstance, null,
                                                                new Type[] { actualType, typeof(EntityKey), typeof(EntitySet), typeof(ObjectContext), typeof(MergeOption), typeof(Type),
                                                                             typeof(Func<object, IPropertyAccessorStrategy>), typeof(Func<object, IChangeTrackingStrategy>), typeof(Func<object, IEntityKeyStrategy>) }, null);
                result = Expression.New(ci, input, keyReader, entitySetReader, Shaper_Context, Expression.Constant(mergeOption, typeof(MergeOption)), Expression.Constant(identityType, typeof(Type)),
                                        propertyAccessorStrategy, changeTrackingStrategy, keyStrategy);
            }
            result = Expression.Convert(result, typeof(IEntityWrapper));
            return result;
        }
 
        /// <summary>
        /// Takes an expression that represents an IEntityWrapper instance and creates a new
        /// expression that extracts the raw entity from this.
        /// </summary>
        internal static Expression Emit_UnwrapAndEnsureType(Expression input, Type type)
        {
            return Translator.Emit_EnsureType(Expression.Property(input, IEntityWrapper_Entity), type);
        }
 
        /// <summary>
        /// Method that the generated expression calls when the types are not 
        /// assignable
        /// </summary>
        private static TTarget CheckedConvert<TSource, TTarget>(TSource value)
        {
            checked
            {
                try
                {
                    return (TTarget)(object)value;
                }
                catch (InvalidCastException)
                {
                    Type valueType = value.GetType();
 
                    // In the case of CompensatingCollection<T>, simply report IEnumerable<T> in the
                    // exception message because the user has no reason to know what the type represents.
                    if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(CompensatingCollection<>))
                    {
                        valueType = typeof(IEnumerable<>).MakeGenericType(valueType.GetGenericArguments());
                    }
                    throw EntityUtil.ValueInvalidCast(valueType, typeof(TTarget));
                }
                catch (NullReferenceException)
                {
                    throw EntityUtil.ValueNullReferenceCast(typeof(TTarget));
                }
            }
        }
 
        /// <summary>
        /// Create expression to compare the results of two expressions and return
        /// whether they are equal.  Note we have special case logic for byte arrays.
        /// </summary>
        private static Expression Emit_Equal(Expression left, Expression right)
        {
            Expression result;
            Debug.Assert(left.Type == right.Type, "equals with different types");
            if (typeof(byte[]) == left.Type)
            {
                result = Expression.Call(Translator_BinaryEquals, left, right);
            }
            else
            {
                result = Expression.Equal(left, right);
            }
            return result;
        }
 
        /// <summary>
        /// Helper method used in expressions generated by Emit_Equal to perform a 
        /// byte-by-byte comparison of two byte arrays.  There really ought to be 
        /// a way to do this in the framework but I'm unaware of it.
        /// </summary>
        private static bool BinaryEquals(byte[] left, byte[] right)
        {
            if (null == left)
            {
                return null == right;
            }
            else if (null == right)
            {
                return false;
            }
            if (left.Length != right.Length)
            {
                return false;
            }
            for (int i = 0; i < left.Length; i++)
            {
                if (left[i] != right[i])
                {
                    return false;
                }
            }
            return true;
        }
 
        /// <summary>
        /// Creates expression to construct an EntityKey. Assumes that both the key has 
        /// a value (Emit_EntityKey_HasValue == true) and that the EntitySet has value 
        /// (EntitySet != null).
        /// </summary>
        private static Expression Emit_EntityKey_ctor(Translator translator, EntityIdentity entityIdentity, bool isForColumnValue, out Expression entitySetReader) 
        {
            Expression result;
            Expression setEntitySetStateSlotValue = null;
 
            // First build the expressions that read each value that comprises the EntityKey
            List<Expression> keyReaders = new List<Expression>(entityIdentity.Keys.Length);
            for (int i = 0; i < entityIdentity.Keys.Length; i++)
            {
                Expression keyReader = entityIdentity.Keys[i].Accept(translator, new TranslatorArg(typeof(object))).Expression;
                keyReaders.Add(keyReader);
            }
 
            // Next build the expression that determines us the entitySet; how we do this differs 
            // depending on whether we have a simple or discriminated identity.
 
            SimpleEntityIdentity simpleEntityIdentity = entityIdentity as SimpleEntityIdentity;
            if (null != simpleEntityIdentity)
            {
                if (simpleEntityIdentity.EntitySet == null)
                {
                    // 'Free-floating' entities do not have entity keys.
                    entitySetReader = Expression.Constant(null, typeof(EntitySet));
                    return Expression.Constant(null, typeof(EntityKey));
                }
                // For SimpleEntityIdentities, the entitySet expression is a constant
                entitySetReader = Expression.Constant(simpleEntityIdentity.EntitySet, typeof(EntitySet));
            }
            else
            {
                // For DiscriminatedEntityIdentities, the we have to search the EntitySetMap 
                // for the matching discriminator value; we'll get the discriminator first, 
                // the compare them all in sequence.                
                DiscriminatedEntityIdentity discriminatedEntityIdentity = (DiscriminatedEntityIdentity)entityIdentity;
 
                Expression discriminator = discriminatedEntityIdentity.EntitySetColumnMap.Accept(translator, new TranslatorArg(typeof(int?))).Expression;
                EntitySet[] entitySets = discriminatedEntityIdentity.EntitySetMap;
 
                // 
 
 
                // (_discriminator == 0 ? entitySets[0] : (_discriminator == 1 ? entitySets[1] ... : null)
                entitySetReader = Expression.Constant(null, typeof(EntitySet));
                for (int i = 0; i < entitySets.Length; i++)
                {
                    entitySetReader = Expression.Condition(
                                                Expression.Equal(discriminator, Expression.Constant(i, typeof(int?))),
                                                Expression.Constant(entitySets[i], typeof(EntitySet)),
                                                entitySetReader
                                                );
                }
 
                // Allocate a stateSlot to contain the entitySet we determine, and ensure we
                // store it there on the way to constructing the key.
                int entitySetStateSlotNumber = translator.AllocateStateSlot();
                setEntitySetStateSlotValue = Emit_Shaper_SetStatePassthrough(entitySetStateSlotNumber, entitySetReader);
                entitySetReader = Emit_Shaper_GetState(entitySetStateSlotNumber, typeof(EntitySet));
            }
 
            // And now that we have all the pieces, construct the EntityKey using the appropriate
            // constructor (there's an optimized constructor for the single key case)
            if (1 == entityIdentity.Keys.Length)
            {
                // new EntityKey(entitySet, keyReaders[0])
                result = Expression.New(EntityKey_ctor_SingleKey,
                                            entitySetReader,
                                            keyReaders[0]);
            }
            else
            {
                // new EntityKey(entitySet, { keyReaders[0], ... keyReaders[n] })
                result = Expression.New(EntityKey_ctor_CompositeKey,
                                            entitySetReader,
                                            Expression.NewArrayInit(typeof(object), keyReaders));
            }
 
            // In the case where we've had to store the entitySetReader value in a 
            // state slot, we test the value for non-null before we construct the 
            // entityKey.  We use this opportunity to stuff the value into the state
            // slot, so the code above that attempts to read it from there will find
            // it.
            if (null != setEntitySetStateSlotValue)
            {
                Expression noEntityKeyExpression;
                if (translator.IsValueLayer && !isForColumnValue)
                {
                    noEntityKeyExpression = Expression.Constant(EntityKey.NoEntitySetKey, typeof(EntityKey));
                }
                else
                {
                    noEntityKeyExpression = Expression.Constant(null, typeof(EntityKey));
                }
                result = Expression.Condition(
                                            Expression.Equal(setEntitySetStateSlotValue, Expression.Constant(null, typeof(EntitySet))),
                                            noEntityKeyExpression,
                                            result
                                            );
            }
            return result;
        }
 
        /// <summary>
        /// Create expression that verifies that the entityKey has a value.  Note we just
        /// presume that if the first key is non-null, all the keys will be valid.
        /// </summary>
        private static Expression Emit_EntityKey_HasValue(SimpleColumnMap[] keyColumns)
        {
            Debug.Assert(0 < keyColumns.Length, "empty keyColumns?");
 
            // !shaper.Reader.IsDBNull(keyColumn[0].ordinal)
            Expression result = Emit_Reader_IsDBNull(keyColumns[0]);
            result = Expression.Not(result);
            return result;
        }
 
        /// <summary>
        /// Create expression to call the GetValue method of the shaper's source data reader
        /// </summary>
        private static Expression Emit_Reader_GetValue(int ordinal, Type type)
        {
            // (type)shaper.Reader.GetValue(ordinal)
            Expression result = Emit_EnsureType(Expression.Call(Shaper_Reader, DbDataReader_GetValue, Expression.Constant(ordinal)), type);
            return result;
        }
 
        /// <summary>
        /// Create expression to call the IsDBNull method of the shaper's source data reader
        /// </summary>
        private static Expression Emit_Reader_IsDBNull(int ordinal)
        {
            // shaper.Reader.IsDBNull(ordinal)
            Expression result = Expression.Call(Shaper_Reader, DbDataReader_IsDBNull, Expression.Constant(ordinal));
            return result;
        }
 
        /// <summary>
        /// Create expression to call the IsDBNull method of the shaper's source data reader 
        /// for the scalar column represented by the column map.
        /// </summary>
        private static Expression Emit_Reader_IsDBNull(ColumnMap columnMap)
        {
            // 
            Expression result = Emit_Reader_IsDBNull(((ScalarColumnMap)columnMap).ColumnPos);
            return result;
        }
 
        /// <summary>
        /// Create expression to read a property value with error handling
        /// </summary>
        private static Expression Emit_Shaper_GetPropertyValueWithErrorHandling(Type propertyType, int ordinal, string propertyName, string typeName, TypeUsage columnType)
        {
            // // shaper.GetSpatialColumnValueWithErrorHandling(ordinal, propertyName, typeName, primitiveColumnType) OR shaper.GetColumnValueWithErrorHandling(ordinal, propertyName, typeName)
            Expression result;
            PrimitiveTypeKind primitiveColumnType;
            if (Helper.IsSpatialType(columnType, out primitiveColumnType))
            {
                result = Expression.Call(Shaper_Parameter, Shaper_GetSpatialPropertyValueWithErrorHandling.MakeGenericMethod(propertyType), 
                    Expression.Constant(ordinal), Expression.Constant(propertyName), Expression.Constant(typeName), Expression.Constant(primitiveColumnType, typeof(PrimitiveTypeKind)));
            }
            else
            {
                result = Expression.Call(Shaper_Parameter, Shaper_GetPropertyValueWithErrorHandling.MakeGenericMethod(propertyType), Expression.Constant(ordinal), Expression.Constant(propertyName), Expression.Constant(typeName));
            }
            return result;
        }
 
        /// <summary>
        /// Create expression to read a column value with error handling
        /// </summary>
        private static Expression Emit_Shaper_GetColumnValueWithErrorHandling(Type resultType, int ordinal, TypeUsage columnType)
        {
            // shaper.GetSpatialColumnValueWithErrorHandling(ordinal, primitiveColumnType) OR shaper.GetColumnValueWithErrorHandling(ordinal)
            Expression result;
            PrimitiveTypeKind primitiveColumnType;
            if (Helper.IsSpatialType(columnType, out primitiveColumnType))
            {
                primitiveColumnType = Helper.IsGeographicType((PrimitiveType)columnType.EdmType) ? PrimitiveTypeKind.Geography : PrimitiveTypeKind.Geometry;
                result = Expression.Call(Shaper_Parameter, Shaper_GetSpatialColumnValueWithErrorHandling.MakeGenericMethod(resultType), Expression.Constant(ordinal), Expression.Constant(primitiveColumnType, typeof(PrimitiveTypeKind)));
            }
            else
            {
                result = Expression.Call(Shaper_Parameter, Shaper_GetColumnValueWithErrorHandling.MakeGenericMethod(resultType), Expression.Constant(ordinal));
            }
            return result;
        }
 
        /// <summary>
        /// Create expression to read a column value of type System.Data.Spatial.DbGeography by delegating to the DbSpatialServices implementation of the underlying provider
        /// </summary>
        private static Expression Emit_Shaper_GetGeographyColumnValue(int ordinal)
        {
            // shaper.GetGeographyColumnValue(ordinal)
            Expression result = Expression.Call(Shaper_Parameter, Shaper_GetGeographyColumnValue, Expression.Constant(ordinal));
            return result;
        }
 
        /// <summary>
        /// Create expression to read a column value of type System.Data.Spatial.DbGeometry by delegating to the DbSpatialServices implementation of the underlying provider
        /// </summary>
        private static Expression Emit_Shaper_GetGeometryColumnValue(int ordinal)
        {
            // shaper.GetGeometryColumnValue(ordinal)
            Expression result = Expression.Call(Shaper_Parameter, Shaper_GetGeometryColumnValue, Expression.Constant(ordinal));
            return result;
        }
 
        /// <summary>
        /// Create expression to read an item from the shaper's state array
        /// </summary>
        private static Expression Emit_Shaper_GetState(int stateSlotNumber, Type type)
        {
            // (type)shaper.State[stateSlotNumber]
            Expression result = Emit_EnsureType(Expression.ArrayIndex(Shaper_State, Expression.Constant(stateSlotNumber)), type);
            return result;
        }
 
        /// <summary>
        /// Create expression to set an item in the shaper's state array
        /// </summary>
        private static Expression Emit_Shaper_SetState(int stateSlotNumber, Expression value)
        {
            // shaper.SetState<T>(stateSlotNumber, value)
            Expression result = Expression.Call(Shaper_Parameter, Shaper_SetState.MakeGenericMethod(value.Type), Expression.Constant(stateSlotNumber), value);
            return result;
        }
 
        /// <summary>
        /// Create expression to set an item in the shaper's state array
        /// </summary>
        private static Expression Emit_Shaper_SetStatePassthrough(int stateSlotNumber, Expression value)
        {
            // shaper.SetState<T>(stateSlotNumber, value)
            Expression result = Expression.Call(Shaper_Parameter, Shaper_SetStatePassthrough.MakeGenericMethod(value.Type), Expression.Constant(stateSlotNumber), value);
            return result;
        }
        #endregion
 
        #region ColumnMapVisitor implementation
 
        // utility accept that looks up CLR type
        private static TranslatorResult AcceptWithMappedType(Translator translator, ColumnMap columnMap, ColumnMap parent)
        {
            Type type = translator.DetermineClrType(columnMap.Type);
            TranslatorResult result = columnMap.Accept(translator, new TranslatorArg(type));
            return result;
        }
 
        #region structured columns
 
        /// <summary>
        /// Visit(ComplexTypeColumnMap)
        /// </summary>
        internal override TranslatorResult Visit(ComplexTypeColumnMap columnMap, TranslatorArg arg)
        {
            Expression result = null;
            Expression nullSentinelCheck = null;
 
            if (null != columnMap.NullSentinel)
            {
                nullSentinelCheck = Emit_Reader_IsDBNull(columnMap.NullSentinel);
            }
 
            if (IsValueLayer)
            {
                result = BuildExpressionToGetRecordState(columnMap, null, null, nullSentinelCheck);
            }
            else
            {
                ComplexType complexType = (ComplexType)columnMap.Type.EdmType;
                Type clrType = DetermineClrType(complexType);
                ConstructorInfo constructor = GetConstructor(clrType);
 
                // Build expressions to read the property values from the source data 
                // reader and bind them to their target properties
                List<MemberBinding> propertyBindings = CreatePropertyBindings(columnMap, clrType, complexType.Properties);
 
                // We have all the property bindings now; go ahead and build the expression to
                // construct the type and store the property values.
                result = Expression.MemberInit(Expression.New(constructor), propertyBindings);
 
                // If there's a null sentinel, then everything above is gated upon whether 
                // it's value is DBNull.Value.
                if (null != nullSentinelCheck)
                {
                    // shaper.Reader.IsDBNull(nullsentinelOridinal) ? (type)null : result
                    result = Expression.Condition(nullSentinelCheck, Emit_NullConstant(result.Type), result);
                }
            }
            return new TranslatorResult(result, arg.RequestedType);
        }
 
        /// <summary>
        /// Visit(EntityColumnMap)
        /// </summary>
        internal override TranslatorResult Visit(EntityColumnMap columnMap, TranslatorArg arg)
        {
            Expression result;
 
            // Build expressions to read the entityKey and determine the entitySet. Note
            // that we attempt to optimize things such that we won't construct anything 
            // that isn't needed, depending upon the interfaces the clrType derives from 
            // and the MergeOption that was requested.
            //
            // We always need the entitySet, except when MergeOption.NoTracking
            //
            // We always need the entityKey, except when MergeOption.NoTracking and the
            // clrType doesn't derive from IEntityWithKey
            EntityIdentity entityIdentity = columnMap.EntityIdentity;
            Expression entitySetReader = null;
            Expression entityKeyReader = Emit_EntityKey_ctor(this, entityIdentity, false, out entitySetReader);
 
            if (IsValueLayer)
            {                
                Expression nullCheckExpression = Expression.Not(Emit_EntityKey_HasValue(entityIdentity.Keys));
                //Expression nullCheckExpression = Emit_EntityKey_HasValue(entityIdentity.Keys);
                result = BuildExpressionToGetRecordState(columnMap, entityKeyReader, entitySetReader, nullCheckExpression);
            }
            else
            {
                Expression constructEntity = null;
 
                EntityType cSpaceType = (EntityType)columnMap.Type.EdmType;
                Debug.Assert(cSpaceType.BuiltInTypeKind == BuiltInTypeKind.EntityType, "Type was " + cSpaceType.BuiltInTypeKind);
                ClrEntityType oSpaceType = (ClrEntityType)LookupObjectMapping(cSpaceType).ClrType;
                Type clrType = oSpaceType.ClrType;
 
                // Build expressions to read the property values from the source data 
                // reader and bind them to their target properties
                List<MemberBinding> propertyBindings = CreatePropertyBindings(columnMap, clrType, cSpaceType.Properties);
 
                // We have all the property bindings now; go ahead and build the expression to
                // construct the entity or proxy and store the property values.  We'll wrap it with more
                // stuff that needs to happen (or not) below.
                EntityProxyTypeInfo proxyTypeInfo = EntityProxyFactory.GetProxyType(oSpaceType);
 
                // If no proxy type exists for the entity, construct the regular entity object.
                // If a proxy type does exist, examine the ObjectContext.ContextOptions.ProxyCreationEnabled flag
                // to determine whether to create a regular or proxy entity object.
 
                Expression constructNonProxyEntity = Emit_ConstructEntity(oSpaceType, propertyBindings, entityKeyReader, entitySetReader, arg, null);
                if (proxyTypeInfo == null)
                {
                    constructEntity = constructNonProxyEntity;
                }
                else
                {
                    Expression constructProxyEntity = Emit_ConstructEntity(oSpaceType, propertyBindings, entityKeyReader, entitySetReader, arg, proxyTypeInfo);
 
                    constructEntity = Expression.Condition(Shaper_ProxyCreationEnabled,
                                                           constructProxyEntity,
                                                           constructNonProxyEntity);
                }
 
                // If we're tracking, call HandleEntity (or HandleIEntityWithKey or 
                // HandleEntityAppendOnly) as appropriate
                if (MergeOption.NoTracking != _mergeOption)
                {
                    Type actualType = proxyTypeInfo == null ? clrType : proxyTypeInfo.ProxyType;
                    if (typeof(IEntityWithKey).IsAssignableFrom(actualType) && MergeOption.AppendOnly != _mergeOption)
                    {
                        constructEntity = Expression.Call(Shaper_Parameter, Shaper_HandleIEntityWithKey.MakeGenericMethod(clrType),
                                                                                            constructEntity,
                                                                                            entitySetReader
                                                                                            );
                    }
                    else
                    {
                        if (MergeOption.AppendOnly == _mergeOption)
                        {
                            // pass through a delegate creating the entity rather than the actual entity, so we can avoid
                            // the cost of materialization when the entity is already in the state manager
 
                            //Func<Shaper, TEntity> entityDelegate = shaper => constructEntity(shaper);
                            LambdaExpression entityDelegate = CreateInlineDelegate(constructEntity);
                            constructEntity = Expression.Call(Shaper_Parameter, Shaper_HandleEntityAppendOnly.MakeGenericMethod(clrType),
                                                                                            entityDelegate,
                                                                                            entityKeyReader,
                                                                                            entitySetReader
                                                                                            );
                        }
                        else
                        {
                            constructEntity = Expression.Call(Shaper_Parameter, Shaper_HandleEntity.MakeGenericMethod(clrType),
                                                                                            constructEntity,
                                                                                            entityKeyReader,
                                                                                            entitySetReader
                                                                                            );
                        }
                    }
                }
                else
                {
                    constructEntity = Expression.Call(Shaper_Parameter, Shaper_HandleEntityNoTracking.MakeGenericMethod(clrType),
                                                                                            constructEntity
                                                                                            );
                }
 
                // All the above is gated upon whether there really is an entity value; 
                // we won't bother executing anything unless there is an entityKey value,
                // otherwise we'll just return a typed null.
                result = Expression.Condition(
                                            Emit_EntityKey_HasValue(entityIdentity.Keys),
                                            constructEntity,
                                            Emit_WrappedNullConstant(arg.RequestedType)
                                            );
            }
 
            return new TranslatorResult(result, arg.RequestedType);
        }
 
        private Expression Emit_ConstructEntity(EntityType oSpaceType, IEnumerable<MemberBinding> propertyBindings, Expression entityKeyReader, Expression entitySetReader, TranslatorArg arg, EntityProxyTypeInfo proxyTypeInfo)
        {
            bool isProxy = proxyTypeInfo != null;
            Type clrType = oSpaceType.ClrType;
            Type actualType;
 
            Expression constructEntity;
 
            if (isProxy)
            {
                constructEntity = Expression.MemberInit(Expression.New(proxyTypeInfo.ProxyType), propertyBindings);
                actualType = proxyTypeInfo.ProxyType;
            }
            else
            {
                ConstructorInfo constructor = GetConstructor(clrType);
                constructEntity = Expression.MemberInit(Expression.New(constructor), propertyBindings);
                actualType = clrType;
            }
 
            // After calling the constructor, immediately create an IEntityWrapper instance for the entity.
            constructEntity = Emit_EnsureTypeAndWrap(constructEntity, entityKeyReader, entitySetReader, arg.RequestedType, clrType, actualType,
                                                     _mergeOption == MergeOption.NoTracking ? MergeOption.NoTracking : MergeOption.AppendOnly, isProxy);
 
            if (isProxy)
            {
                // Since we created a proxy, we now need to give it a reference to the wrapper that we just created.
                constructEntity = Expression.Call(Expression.Constant(proxyTypeInfo), EntityProxyTypeInfo_SetEntityWrapper, constructEntity);
 
                if (proxyTypeInfo.InitializeEntityCollections != null)
                {
                    constructEntity = Expression.Call(proxyTypeInfo.InitializeEntityCollections, constructEntity);
                }
            }
 
            return constructEntity;
        }
 
        /// <summary>
        /// Prepare a list of PropertyBindings for each item in the specified property 
        /// collection such that the mapped property of the specified clrType has its
        /// value set from the source data reader.  
        /// 
        /// Along the way we'll keep track of non-public properties and properties that
        /// have link demands, so we can ensure enforce them.
        /// </summary>
        private List<MemberBinding> CreatePropertyBindings(StructuredColumnMap columnMap, Type clrType, ReadOnlyMetadataCollection<EdmProperty> properties)
        {
            List<MemberBinding> result = new List<MemberBinding>(columnMap.Properties.Length);
 
            ObjectTypeMapping mapping = LookupObjectMapping(columnMap.Type.EdmType);
 
            for (int i = 0; i < columnMap.Properties.Length; i++)
            {
                EdmProperty edmProperty = mapping.GetPropertyMap(properties[i].Name).ClrProperty;
 
                // get MethodInfo for setter
                MethodInfo propertyAccessor;
                Type propertyType;
                LightweightCodeGenerator.ValidateSetterProperty(edmProperty.EntityDeclaringType, edmProperty.PropertySetterHandle, out propertyAccessor, out propertyType);
 
                // determine if any security checks are required
                if (!LightweightCodeGenerator.IsPublic(propertyAccessor))
                {
                    _hasNonPublicMembers = true;
                }
 
                // get translation of property value
                Expression valueReader = columnMap.Properties[i].Accept(this, new TranslatorArg(propertyType)).Expression;
 
                ScalarColumnMap scalarColumnMap = columnMap.Properties[i] as ScalarColumnMap;
                if (null != scalarColumnMap)
                {
                    string propertyName = propertyAccessor.Name.Substring(4); // substring to strip "set_"
 
                    // create a value reader with error handling
                    Expression valueReaderWithErrorHandling = Emit_Shaper_GetPropertyValueWithErrorHandling(propertyType, scalarColumnMap.ColumnPos, propertyName, propertyAccessor.DeclaringType.Name, scalarColumnMap.Type);
                    _currentCoordinatorScratchpad.AddExpressionWithErrorHandling(valueReader, valueReaderWithErrorHandling);
                }
 
                Type entityDeclaringType = Type.GetTypeFromHandle(edmProperty.EntityDeclaringType);
                MemberBinding binding = Expression.Bind(GetProperty(propertyAccessor, entityDeclaringType), valueReader);
                result.Add(binding);
            }
            return result;
        }
 
        /// <summary>
        /// Gets the PropertyInfo representing the property with which the given setter method is associated.
        /// This code is taken from Expression.Bind(MethodInfo) but adapted to take a type such that it
        /// will work in cases in which the property was declared on a generic base class.  In such cases,
        /// the declaringType needs to be the actual entity type, rather than the base class type.  Note that
        /// declaringType can be null, in which case the setterMethod.DeclaringType is used.
        /// </summary>
        private static PropertyInfo GetProperty(MethodInfo setterMethod, Type declaringType)
        {
            if (declaringType == null)
            {
                declaringType = setterMethod.DeclaringType;
            }
            BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
            foreach (PropertyInfo propertyInfo in declaringType.GetProperties(bindingAttr))
            {
                if (propertyInfo.GetSetMethod(nonPublic: true) == setterMethod)
                {
                    return propertyInfo;
                }
            }
            Debug.Fail("Should always find a property for the setterMethod since we got the setter method from a property in the first place.");
            return null;
        }
 
        /// <summary>
        /// Visit(SimplePolymorphicColumnMap)
        /// </summary>
        internal override TranslatorResult Visit(SimplePolymorphicColumnMap columnMap, TranslatorArg arg)
        {
            Expression result;
 
            // We're building a conditional ladder, where we'll compare each 
            // discriminator value with the one from the source data reader, and 
            // we'll pick that type if they match.
            Expression discriminatorReader = AcceptWithMappedType(this, columnMap.TypeDiscriminator, columnMap).Expression;
 
            if (IsValueLayer)
            {
                result = Emit_EnsureType(
                                BuildExpressionToGetRecordState(columnMap, null, null, Expression.Constant(true)),
                                arg.RequestedType);
            }
            else
            {
                result = Emit_WrappedNullConstant(arg.RequestedType); // the default
            }
 
            foreach (var typeChoice in columnMap.TypeChoices)
            {
                // determine CLR type for the type choice, and don't bother adding 
                // this choice if it can't produce a result
                Type type = DetermineClrType(typeChoice.Value.Type);
 
                if (type.IsAbstract)
                {
                    continue;
                }
 
                Expression discriminatorConstant = Expression.Constant(typeChoice.Key, discriminatorReader.Type);
                Expression discriminatorMatches;
 
                // For string types, we have to use a specific comparison that handles
                // trailing spaces properly, not just the general equality test we use 
                // elsewhere.
                if (discriminatorReader.Type == typeof(string))
                {
                    discriminatorMatches = Expression.Call(Expression.Constant(TrailingSpaceStringComparer.Instance), IEqualityComparerOfString_Equals, discriminatorConstant, discriminatorReader);
                }
                else
                {
                    discriminatorMatches = Emit_Equal(discriminatorConstant, discriminatorReader);
                }
 
                result = Expression.Condition(discriminatorMatches,
                                            typeChoice.Value.Accept(this, arg).Expression,
                                            result);
 
            }
            return new TranslatorResult(result, arg.RequestedType);
        }
 
        /// <summary>
        /// Visit(MultipleDiscriminatorPolymorphicColumnMap)
        /// </summary>
        [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
        internal override TranslatorResult Visit(MultipleDiscriminatorPolymorphicColumnMap columnMap, TranslatorArg arg)
        {
            MethodInfo multipleDiscriminatorPolymorphicColumnMapHelper = Translator_MultipleDiscriminatorPolymorphicColumnMapHelper.MakeGenericMethod(arg.RequestedType);
            Expression result = (Expression)multipleDiscriminatorPolymorphicColumnMapHelper.Invoke(this, new object[] { columnMap, arg });
            return new TranslatorResult(result, arg.RequestedType);
        }
 
        /// <summary>
        /// Helper method to simplify the construction of the types; I'm just too lazy to 
        /// create all the nested generic types needed to this by hand.
        /// </summary>
        private Expression MultipleDiscriminatorPolymorphicColumnMapHelper<TElement>(MultipleDiscriminatorPolymorphicColumnMap columnMap, TranslatorArg arg)
        {
            // construct an array of discriminator values
            Expression[] discriminatorReaders = new Expression[columnMap.TypeDiscriminators.Length];
            for (int i = 0; i < discriminatorReaders.Length; i++)
            {
                discriminatorReaders[i] = columnMap.TypeDiscriminators[i].Accept(this, new TranslatorArg(typeof(object))).Expression;
            }
            Expression discriminatorValues = Expression.NewArrayInit(typeof(object), discriminatorReaders);
 
            // Next build the expressions that will construct the type choices. An array of KeyValuePair<EntityType, Func<Shaper, TElement>>
            List<Expression> elementDelegates = new List<Expression>();
            Type typeDelegatePairType = typeof(KeyValuePair<EntityType, Func<Shaper, TElement>>);
            ConstructorInfo typeDelegatePairConstructor = typeDelegatePairType.GetConstructor(new Type[] { typeof(EntityType), typeof(Func<Shaper, TElement>) });
            foreach (var typeChoice in columnMap.TypeChoices)
            {
                Expression typeReader = Emit_EnsureType(AcceptWithMappedType(this, typeChoice.Value, columnMap).UnwrappedExpression, typeof(TElement));
                LambdaExpression typeReaderDelegate = CreateInlineDelegate(typeReader);
                Expression typeDelegatePair = Expression.New(
                                                    typeDelegatePairConstructor, 
                                                    Expression.Constant(typeChoice.Key), 
                                                    typeReaderDelegate
                                                    );
                elementDelegates.Add(typeDelegatePair);
            }
 
            // invoke shaper.Discrimate({ discriminatorValue1...discriminatorValueN }, discriminateDelegate, elementDelegates)
            MethodInfo shaperDiscriminateOfT = Shaper_Discriminate.MakeGenericMethod(typeof(TElement));
            Expression result = Expression.Call(Shaper_Parameter, shaperDiscriminateOfT,
                                                    discriminatorValues,
                                                    Expression.Constant(columnMap.Discriminate),
                                                    Expression.NewArrayInit(typeDelegatePairType, elementDelegates)
                                                    );
            return result;
        }
 
        /// <summary>
        /// Visit(RecordColumnMap)
        /// </summary>
        internal override TranslatorResult Visit(RecordColumnMap columnMap, TranslatorArg arg)
        {
            Expression result = null;
            Expression nullSentinelCheck = null;
 
            if (null != columnMap.NullSentinel)
            {
                nullSentinelCheck = Emit_Reader_IsDBNull(columnMap.NullSentinel);
            }
 
            if (IsValueLayer)
            {
                result = BuildExpressionToGetRecordState(columnMap, null, null, nullSentinelCheck);
            }
            else
            {
                Debug.Assert(columnMap.Type.EdmType.BuiltInTypeKind == BuiltInTypeKind.RowType, "RecordColumnMap without RowType?"); // we kind of depend upon this 
                Expression nullConstant;
 
                // There are (at least) three different reasons we have a RecordColumnMap
                // so pick the method that handles the reason we have for this one.
                InitializerMetadata initializerMetadata;
                if (InitializerMetadata.TryGetInitializerMetadata(columnMap.Type, out initializerMetadata))
                {
                    result = HandleLinqRecord(columnMap, initializerMetadata);
                    nullConstant = Emit_NullConstant(result.Type);
                }
                else
                {
                    RowType spanRowType = (RowType)columnMap.Type.EdmType;
 
                    if (null != _spanIndex && _spanIndex.HasSpanMap(spanRowType))
                    {
                        result = HandleSpandexRecord(columnMap, arg, spanRowType);
                        nullConstant = Emit_WrappedNullConstant(result.Type);
                    }
                    else
                    {
                        result = HandleRegularRecord(columnMap, arg, spanRowType);
                        nullConstant = Emit_NullConstant(result.Type);
                    }
                }
 
                // If there is a null sentinel process it accordingly.
                if (null != nullSentinelCheck)
                {
                    // shaper.Reader.IsDBNull(nullsentinelOridinal) ? (type)null : result
                    result = Expression.Condition(nullSentinelCheck, nullConstant, result);
                }
            }
            return new TranslatorResult(result, arg.RequestedType);
        }
 
        private Expression BuildExpressionToGetRecordState(StructuredColumnMap columnMap, Expression entityKeyReader, Expression entitySetReader, Expression nullCheckExpression)
        {
            RecordStateScratchpad recordStateScratchpad = _currentCoordinatorScratchpad.CreateRecordStateScratchpad();
 
            int stateSlotNumber = AllocateStateSlot();
            recordStateScratchpad.StateSlotNumber = stateSlotNumber;
 
            int propertyCount = columnMap.Properties.Length;
            int readerCount = (null != entityKeyReader) ? propertyCount + 1 : propertyCount;
 
            recordStateScratchpad.ColumnCount = propertyCount;
 
            // We can have an entity here, even though it's a RecordResultColumn, because
            // it may be a polymorphic type; eg: TREAT(Product AS DiscontinuedProduct); we
            // construct an EntityRecordInfo with a sentinel EntityNotValidKey as it's Key
            EntityType entityTypeMetadata = null;
            if (TypeHelpers.TryGetEdmType<EntityType>(columnMap.Type, out entityTypeMetadata))
            {
                recordStateScratchpad.DataRecordInfo = new EntityRecordInfo(entityTypeMetadata, EntityKey.EntityNotValidKey, null);
            }
            else
            {
                TypeUsage edmType = Helper.GetModelTypeUsage(columnMap.Type);
                recordStateScratchpad.DataRecordInfo = new DataRecordInfo(edmType);
            }
 
            Expression[] propertyReaders = new Expression[readerCount];
            string[] propertyNames = new string[recordStateScratchpad.ColumnCount];
            TypeUsage[] typeUsages = new TypeUsage[recordStateScratchpad.ColumnCount];
 
            for (int ordinal = 0; ordinal < propertyCount; ordinal++)
            {
                Expression propertyReader = columnMap.Properties[ordinal].Accept(this, new TranslatorArg(typeof(Object))).Expression;
 
                // recordState.SetColumnValue(i, propertyReader ?? DBNull.Value)
                propertyReaders[ordinal] = Expression.Call(Shaper_Parameter, Shaper_SetColumnValue, 
                                                        Expression.Constant(stateSlotNumber),
                                                        Expression.Constant(ordinal), 
                                                        Expression.Coalesce(propertyReader, DBNull_Value)
                                                    );
 
                propertyNames[ordinal] = columnMap.Properties[ordinal].Name;
                typeUsages[ordinal] = columnMap.Properties[ordinal].Type;
            }
 
            if (null != entityKeyReader)
            {
                propertyReaders[readerCount - 1] = Expression.Call(Shaper_Parameter, Shaper_SetEntityRecordInfo,
                                                        Expression.Constant(stateSlotNumber),
                                                        entityKeyReader,
                                                        entitySetReader);
            }
 
            recordStateScratchpad.GatherData = Emit_BitwiseOr(propertyReaders);
            recordStateScratchpad.PropertyNames = propertyNames;
            recordStateScratchpad.TypeUsages = typeUsages;
 
            // Finally, build the expression to read the recordState from the shaper state
 
            // (RecordState)shaperState.State[stateSlotNumber].GatherData(shaper)           
            Expression result = Expression.Call(Emit_Shaper_GetState(stateSlotNumber, typeof(RecordState)), RecordState_GatherData, Shaper_Parameter);
 
            // If there's a null check, then everything above is gated upon whether 
            // it's value is DBNull.Value.
            if (null != nullCheckExpression)
            {
                Expression nullResult = Expression.Call(Emit_Shaper_GetState(stateSlotNumber, typeof(RecordState)), RecordState_SetNullRecord, Shaper_Parameter);
                // nullCheckExpression ? (type)null : result
                result = Expression.Condition(nullCheckExpression, nullResult, result);
            }
            return result;
        }
 
        /// <summary>
        /// Build expression to materialize LINQ initialization types (anonymous 
        /// types, IGrouping, EntityCollection)
        /// </summary>
        private Expression HandleLinqRecord(RecordColumnMap columnMap, InitializerMetadata initializerMetadata)
        {
            List<TranslatorResult> propertyReaders = new List<TranslatorResult>(columnMap.Properties.Length);
 
            foreach (var pair in columnMap.Properties.Zip(initializerMetadata.GetChildTypes()))
            {
                ColumnMap propertyColumnMap = pair.Key;
                Type type = pair.Value;
 
                // Note that we're not just blindly using the type from the column map
                // because we need to match the type thatthe initializer says it needs; 
                // that's why were not using AcceptWithMappedType;
                if (null == type)
                {
                    type = DetermineClrType(propertyColumnMap.Type);
                }
 
                TranslatorResult propertyReader = propertyColumnMap.Accept(this, new TranslatorArg(type));
                propertyReaders.Add(propertyReader);
            }
 
            Expression result = initializerMetadata.Emit(this, propertyReaders);
            return result;
        }
 
        /// <summary>
        /// Build expression to materialize a data record.
        /// </summary>
        private Expression HandleRegularRecord(RecordColumnMap columnMap, TranslatorArg arg, RowType spanRowType)
        {
            // handle regular records
 
            // Build an array of expressions that read the individual values from the 
            // source data reader.
            Expression[] columnReaders = new Expression[columnMap.Properties.Length];
            for (int i = 0; i < columnReaders.Length; i++)
            {
                Expression columnReader = AcceptWithMappedType(this, columnMap.Properties[i], columnMap).UnwrappedExpression;
 
                // ((object)columnReader) ?? DBNull.Value
                columnReaders[i] = Expression.Coalesce(Emit_EnsureType(columnReader, typeof(object)), DBNull_Value);
            }
            // new object[] {columnReader0..columnReaderN}
            Expression columnReaderArray = Expression.NewArrayInit(typeof(object), columnReaders);
 
 
            // Get an expression representing the TypeUsage of the MaterializedDataRecord 
            // we're about to construct; we need to remove the span information from it, 
            // though, since we don't want to surface that...
            TypeUsage type = columnMap.Type;
            if (null != _spanIndex)
            {
                type = _spanIndex.GetSpannedRowType(spanRowType) ?? type;
            }
            Expression typeUsage = Expression.Constant(type, typeof(TypeUsage));
 
            // new MaterializedDataRecord(Shaper.Workspace, typeUsage, values)
            Expression result = Emit_EnsureType(Expression.New(MaterializedDataRecord_ctor, Shaper_Workspace, typeUsage, columnReaderArray), arg.RequestedType);
            return result;
        }
 
        /// <summary>
        /// Build expression to materialize the spanned information
        /// </summary>
        private Expression HandleSpandexRecord(RecordColumnMap columnMap, TranslatorArg arg, RowType spanRowType)
        {
            Dictionary<int, AssociationEndMember> spanMap = _spanIndex.GetSpanMap(spanRowType);
 
            // First, build the expression to materialize the root item.
            Expression result = columnMap.Properties[0].Accept(this, arg).Expression;
 
            // Now build expressions that call into the appropriate shaper method
            // for the type of span for each spanned item.
            for (int i = 1; i < columnMap.Properties.Length; i++)
            {
                AssociationEndMember targetMember = spanMap[i];
                TranslatorResult propertyTranslatorResult = AcceptWithMappedType(this, columnMap.Properties[i], columnMap);
                Expression spannedResultReader = propertyTranslatorResult.Expression;
 
                // figure out the flavor of the span
                CollectionTranslatorResult collectionTranslatorResult = propertyTranslatorResult as CollectionTranslatorResult;
                if (null != collectionTranslatorResult)
                {
                    Expression expressionToGetCoordinator = collectionTranslatorResult.ExpressionToGetCoordinator;
 
                    // full span collection
                    Type elementType = spannedResultReader.Type.GetGenericArguments()[0];
 
                    MethodInfo handleFullSpanCollectionMethod = Shaper_HandleFullSpanCollection.MakeGenericMethod(arg.RequestedType, elementType);
                    result = Expression.Call(Shaper_Parameter, handleFullSpanCollectionMethod, result, expressionToGetCoordinator, Expression.Constant(targetMember));
                }
                else
                {
                    if (typeof(EntityKey) == spannedResultReader.Type)
                    {
                        // relationship span
                        MethodInfo handleRelationshipSpanMethod = Shaper_HandleRelationshipSpan.MakeGenericMethod(arg.RequestedType);
                        result = Expression.Call(Shaper_Parameter, handleRelationshipSpanMethod, result, spannedResultReader, Expression.Constant(targetMember));
                    }
                    else
                    {
                        // full span element
                        MethodInfo handleFullSpanElementMethod = Shaper_HandleFullSpanElement.MakeGenericMethod(arg.RequestedType, spannedResultReader.Type);
                        result = Expression.Call(Shaper_Parameter, handleFullSpanElementMethod, result, spannedResultReader, Expression.Constant(targetMember));
                    }
                }
            }
            return result;
        }
 
        #endregion
 
        #region collection columns
 
        /// <summary>
        /// Visit(SimpleCollectionColumnMap)
        /// </summary>
        internal override TranslatorResult Visit(SimpleCollectionColumnMap columnMap, TranslatorArg arg)
        {
            return ProcessCollectionColumnMap(columnMap, arg);
        }
 
        /// <summary>
        /// Visit(DiscriminatedCollectionColumnMap)
        /// </summary>
        internal override TranslatorResult Visit(DiscriminatedCollectionColumnMap columnMap, TranslatorArg arg)
        {
            return ProcessCollectionColumnMap(columnMap, arg, columnMap.Discriminator, columnMap.DiscriminatorValue);
        }
 
        /// <summary>
        /// Common code for both Simple and Discrminated Column Maps.
        /// </summary>
        private TranslatorResult ProcessCollectionColumnMap(CollectionColumnMap columnMap, TranslatorArg arg)
        {
            return ProcessCollectionColumnMap(columnMap, arg, null, null);
        }
 
        /// <summary>
        /// Common code for both Simple and Discrminated Column Maps.
        /// </summary>
        private TranslatorResult ProcessCollectionColumnMap(CollectionColumnMap columnMap, TranslatorArg arg, ColumnMap discriminatorColumnMap, object discriminatorValue)
        {
            Type elementType = DetermineElementType(arg.RequestedType, columnMap);
 
            // CoordinatorScratchpad aggregates information about the current nested
            // result (represented by the given CollectionColumnMap)
            CoordinatorScratchpad coordinatorScratchpad = new CoordinatorScratchpad(elementType);
 
            // enter scope for current coordinator when translating children, etc.
            EnterCoordinatorTranslateScope(coordinatorScratchpad);
 
 
            ColumnMap elementColumnMap = columnMap.Element;
 
            if (IsValueLayer)
            {
                StructuredColumnMap structuredElement = elementColumnMap as StructuredColumnMap;
 
                // If we have a collection of non-structured types we have to put 
                // a structure around it, because we don't have data readers of 
                // scalars, only structures.  We don't need a null sentinel because
                // this structure can't ever be null.
                if (null == structuredElement)
                {
                    ColumnMap[] columnMaps = new ColumnMap[1] { columnMap.Element };
                    elementColumnMap = new RecordColumnMap(columnMap.Element.Type, columnMap.Element.Name, columnMaps, null);
                }
            }
 
            // Build the expression that will construct the element of the collection
            // from the source data reader.
            // We use UnconvertedExpression here so we can defer doing type checking in case
            // we need to translate to a POCO collection later in the process.
            Expression elementReader = elementColumnMap.Accept(this, new TranslatorArg(elementType)).UnconvertedExpression;
 
            // Build the expression(s) that read the collection's keys from the source
            // data reader; note that the top level collection may not have keys if there
            // are no children.
            Expression[] keyReaders;
 
            if (null != columnMap.Keys)
            {
                keyReaders = new Expression[columnMap.Keys.Length];
                for (int i = 0; i < keyReaders.Length; i++)
                {
                    Expression keyReader = AcceptWithMappedType(this, columnMap.Keys[i], columnMap).Expression;
                    keyReaders[i] = keyReader;
                }
            }
            else
            {
                keyReaders = new Expression[] { };
            }
 
            // Build the expression that reads the discriminator value from the source
            // data reader.
            Expression discriminatorReader = null;
            if (null != discriminatorColumnMap)
            {
                discriminatorReader = AcceptWithMappedType(this, discriminatorColumnMap, columnMap).Expression;
            }
 
            // get expression retrieving the coordinator
            Expression expressionToGetCoordinator = BuildExpressionToGetCoordinator(elementType, elementReader, keyReaders, discriminatorReader, discriminatorValue, coordinatorScratchpad);
            MethodInfo getElementsExpression = typeof(Coordinator<>).MakeGenericType(elementType).GetMethod("GetElements", BindingFlags.NonPublic | BindingFlags.Instance);
 
            Expression result;
            if (IsValueLayer)
            {
                result = expressionToGetCoordinator;
            }
            else
            {
                // coordinator.GetElements()
                result = Expression.Call(expressionToGetCoordinator, getElementsExpression);
 
                // Perform the type check that was previously deferred so we could process POCO collections.
                coordinatorScratchpad.Element = Emit_EnsureType(coordinatorScratchpad.Element, elementType);
 
                // When materializing specifically requested collection types, we need
                // to transfer the results from the Enumerable to the requested collection.
                Type innerElementType;
                if (EntityUtil.TryGetICollectionElementType(arg.RequestedType, out innerElementType))
                {
                    // Given we have some type that implements ICollection<T>, we need to decide what concrete
                    // collection type to instantiate--See EntityUtil.DetermineCollectionType for details.
                    var typeToInstantiate = EntityUtil.DetermineCollectionType(arg.RequestedType);
 
                    if (typeToInstantiate == null)
                    {
                        throw EntityUtil.InvalidOperation(Strings.ObjectQuery_UnableToMaterializeArbitaryProjectionType(arg.RequestedType));
                    }
 
                    Type listOfElementType = typeof(List<>).MakeGenericType(innerElementType);
                    if (typeToInstantiate != listOfElementType)
                    {
                        coordinatorScratchpad.InitializeCollection = Emit_EnsureType(
                            Expression.New(GetConstructor(typeToInstantiate)),
                            typeof(ICollection<>).MakeGenericType(innerElementType));
                    }
                    result = Emit_EnsureType(result, arg.RequestedType);
                }
                else
                {
                    // If any compensation is required (returning IOrderedEnumerable<T>, not 
                    // just vanilla IEnumerable<T> we must wrap the result with a static class
                    // that is of the type expected.
                    if (!arg.RequestedType.IsAssignableFrom(result.Type))
                    {
                        // new CompensatingCollection<TElement>(_collectionReader)
                        Type compensatingCollectionType = typeof(CompensatingCollection<>).MakeGenericType(elementType);
                        ConstructorInfo constructorInfo = compensatingCollectionType.GetConstructors()[0];
                        result = Emit_EnsureType(Expression.New(constructorInfo, result), compensatingCollectionType);
                    }
                }
            }
            ExitCoordinatorTranslateScope();
            return new CollectionTranslatorResult(result, columnMap, arg.RequestedType, expressionToGetCoordinator);
        }
 
        /// <summary>
        /// Returns the CLR Type of the element of the collection
        /// </summary>
        private Type DetermineElementType(Type collectionType, CollectionColumnMap columnMap)
        {
            Type result = null;
 
            if (IsValueLayer)
            {
                result = typeof(RecordState);
            }
            else
            {
                result = TypeSystem.GetElementType(collectionType);
 
                // GetElementType returns the input type if it is not a collection.
                if (result == collectionType)
                {
                    // if the user isn't asking for a CLR collection type (e.g. ObjectQuery<object>("{{1, 2}}")), we choose for them
                    TypeUsage edmElementType = ((CollectionType)columnMap.Type.EdmType).TypeUsage; // the TypeUsage of the Element of the collection.
                    result = DetermineClrType(edmElementType);
                }
            }
            return result;
        }
 
        /// <summary>
        /// Build up the coordinator graph using Enter/ExitCoordinatorTranslateScope.
        /// </summary>
        private void EnterCoordinatorTranslateScope(CoordinatorScratchpad coordinatorScratchpad)
        {
            if (null == _rootCoordinatorScratchpad)
            {
                coordinatorScratchpad.Depth = 0;
                _rootCoordinatorScratchpad = coordinatorScratchpad;
                _currentCoordinatorScratchpad = coordinatorScratchpad;
            }
            else
            {
                coordinatorScratchpad.Depth = _currentCoordinatorScratchpad.Depth + 1;
                _currentCoordinatorScratchpad.AddNestedCoordinator(coordinatorScratchpad);
                _currentCoordinatorScratchpad = coordinatorScratchpad;
            }
        }
 
        private void ExitCoordinatorTranslateScope()
        {
            _currentCoordinatorScratchpad = _currentCoordinatorScratchpad.Parent;
        }
 
        /// <summary>
        /// Return an expression to read the coordinator from a state slot at 
        /// runtime.  This is the method where we store the expressions we've
        /// been building into the CoordinatorScratchpad, which we'll compile
        /// later, once we've left the visitor.
        /// </summary>
        private Expression BuildExpressionToGetCoordinator(Type elementType, Expression element, Expression[] keyReaders, Expression discriminator, object discriminatorValue, CoordinatorScratchpad coordinatorScratchpad)
        {
            int stateSlotNumber = AllocateStateSlot();
            coordinatorScratchpad.StateSlotNumber = stateSlotNumber;
 
            // Ensure that the element type of the collec element translator
            coordinatorScratchpad.Element = element;
 
            // Build expressions to set the key values into their state slots, and
            // to compare the current values from the source reader with the values
            // in the slots.
            List<Expression> setKeyTerms = new List<Expression>(keyReaders.Length);
            List<Expression> checkKeyTerms = new List<Expression>(keyReaders.Length);
 
            foreach (Expression keyReader in keyReaders)
            {
                // allocate space for the key value in the reader state
                int keyStateSlotNumber = AllocateStateSlot();
 
                // SetKey: readerState.SetState<T>(stateSlot, keyReader)
                setKeyTerms.Add(Emit_Shaper_SetState(keyStateSlotNumber, keyReader));
 
                // CheckKey: ((T)readerState.State[ordinal]).Equals(keyValue)
                checkKeyTerms.Add(Emit_Equal(
                                        Emit_Shaper_GetState(keyStateSlotNumber, keyReader.Type), 
                                        keyReader
                                        )
                                 );
            }
 
            // For setting keys, we use BitwiseOr so that we don't short-circuit (all  
            // key terms are set)
            coordinatorScratchpad.SetKeys = Emit_BitwiseOr(setKeyTerms);
 
            // When checking for equality, we use AndAlso so that we short-circuit (return
            // as soon as key values don't match)
            coordinatorScratchpad.CheckKeys = Emit_AndAlso(checkKeyTerms);
 
            if (null != discriminator)
            {
                // discriminatorValue == discriminator
                coordinatorScratchpad.HasData = Emit_Equal(   
                                                    Expression.Constant(discriminatorValue, discriminator.Type), 
                                                    discriminator
                                                    );
            }
 
            // Finally, build the expression to read the coordinator from the state
            // (Coordinator<elementType>)readerState.State[stateOrdinal]
            Expression result = Emit_Shaper_GetState(stateSlotNumber, typeof(Coordinator<>).MakeGenericType(elementType));
            return result;
        }
 
        #endregion
 
        #region "scalar" columns
 
        /// <summary>
        /// Visit(RefColumnMap)
        /// 
        /// If the entityKey has a value, then return it otherwise return a null 
        /// valued EntityKey.  The EntityKey construction is the tricky part.
        /// </summary>
        internal override TranslatorResult Visit(RefColumnMap columnMap, TranslatorArg arg)
        {
            EntityIdentity entityIdentity = columnMap.EntityIdentity;
            Expression entitySetReader; // Ignored here; used when constructing Entities
 
            // hasValue ? entityKey : (EntityKey)null
            Expression result = Expression.Condition(
                                                Emit_EntityKey_HasValue(entityIdentity.Keys),
                                                Emit_EntityKey_ctor(this, entityIdentity, true, out entitySetReader),
                                                Expression.Constant(null, typeof(EntityKey))
                                                );
            return new TranslatorResult(result, arg.RequestedType);
        }
 
        /// <summary>
        /// Visit(ScalarColumnMap)
        /// 
        /// Pretty basic stuff here; we just call the method that matches the
        /// type of the column.  Of course we have to handle nullable/non-nullable
        /// types, and non-value types.
        /// </summary>
        internal override TranslatorResult Visit(ScalarColumnMap columnMap, TranslatorArg arg)
        {
            Type type = arg.RequestedType;
            TypeUsage columnType = columnMap.Type;
            int ordinal = columnMap.ColumnPos;
            Expression result;
            
            // 1. Create an expression to access the column value as an instance of the correct type. For non-spatial types this requires a call to one of the
            //    DbDataReader GetXXX methods; spatial values must be read using the provider's spatial services implementation.
            // 2. If the type was nullable (strings, byte[], Nullable<T>), wrap the expression with a check for the DBNull value and produce the correct typed null instead.
            //    Since the base spatial types (DbGeography/DbGeometry) are reference types, this is always required for spatial columns.
            // 3. Also create a version of the expression with error handling so that we can throw better exception messages when needed
            //
            PrimitiveTypeKind typeKind;
            if (Helper.IsSpatialType(columnType, out typeKind))
            {
                Debug.Assert(Helper.IsGeographicType((PrimitiveType)columnType.EdmType) || Helper.IsGeometricType((PrimitiveType)columnType.EdmType), "Spatial primitive type is neither Geometry or Geography?");
                result = Emit_Conditional_NotDBNull(Helper.IsGeographicType((PrimitiveType)columnType.EdmType) ? Emit_EnsureType(Emit_Shaper_GetGeographyColumnValue(ordinal), type)
                                                                                            : Emit_EnsureType(Emit_Shaper_GetGeometryColumnValue(ordinal), type),
                                                    ordinal, type);
            }
            else
            {
                bool needsNullableCheck;
                MethodInfo readerMethod = GetReaderMethod(type, out needsNullableCheck);
 
                result = Expression.Call(Shaper_Reader, readerMethod, Expression.Constant(ordinal));
 
                // if the requested type is a nullable enum we need to cast it first to the non-nullable enum type to avoid InvalidCastException.
                // Note that we guard against null values by wrapping the expression with DbNullCheck later. Also we don't actually 
                // look at the type of the value returned by reader. If the value is not castable to enum we will fail with cast exception.
                Type nonNullableType = TypeSystem.GetNonNullableType(type);
                if (nonNullableType.IsEnum && nonNullableType != type)
                {
                    Debug.Assert(needsNullableCheck, "This is a nullable enum so needsNullableCheck should be true to emit code that handles null values read from the reader.");
 
                    result = Expression.Convert(result, nonNullableType);
                }
                else if(type == typeof(object))
                {
                    Debug.Assert(!needsNullableCheck, "If the requested type is object there is no special handling for null values returned from the reader.");
 
                    // special case for an OSpace query where the requested type is object but the column type is of an enum type. In this case
                    // we want to return a boxed value of enum type instead a boxed value of the enum underlying type. We also need to handle null
                    // values to return DBNull to be consistent with behavior for primitive types (e.g. int)
                    if (!IsValueLayer && TypeSemantics.IsEnumerationType(columnType))
                    {
                        result = Expression.Condition(
                                    Emit_Reader_IsDBNull(ordinal),
                                        result,
                                        Expression.Convert(Expression.Convert(result, TypeSystem.GetNonNullableType(DetermineClrType(columnType.EdmType))), typeof(object)));
                    }
                }
 
                // (type)shaper.Reader.Get???(ordinal)
                result = Emit_EnsureType(result, type);
                
                if (needsNullableCheck)
                {
                    result = Emit_Conditional_NotDBNull(result, ordinal, type);
                }
            }
 
            Expression resultWithErrorHandling = Emit_Shaper_GetColumnValueWithErrorHandling(arg.RequestedType, ordinal, columnType);
            _currentCoordinatorScratchpad.AddExpressionWithErrorHandling(result, resultWithErrorHandling);
            return new TranslatorResult(result, type);
        }
 
        private static Expression Emit_Conditional_NotDBNull(Expression result, int ordinal, Type columnType)
        {
            result = Expression.Condition(Emit_Reader_IsDBNull(ordinal),
                                          Expression.Constant(TypeSystem.GetDefaultValue(columnType), columnType),
                                          result);
            return result;
        }
 
        internal static MethodInfo GetReaderMethod(Type type, out bool isNullable)
        {
            Debug.Assert(null != type, "type required");
 
            MethodInfo result;
            isNullable = false;
 
            // determine if this is a Nullable<T>
            Type underlyingType = Nullable.GetUnderlyingType(type);
            if (null != underlyingType)
            {
                isNullable = true;
                type = underlyingType;
            }
            
            TypeCode typeCode = Type.GetTypeCode(type);
 
            switch (typeCode)
            {
                case TypeCode.String:
                    result = DbDataReader_GetString;
                    isNullable = true;
                    break;
                case TypeCode.Int16:
                    result = DbDataReader_GetInt16;
                    break;
                case TypeCode.Int32:
                    result = DbDataReader_GetInt32;
                    break;
                case TypeCode.Int64:
                    result = DbDataReader_GetInt64;
                    break;
                case TypeCode.Boolean:
                    result = DbDataReader_GetBoolean;
                    break;
                case TypeCode.Decimal:
                    result = DbDataReader_GetDecimal;
                    break;
                case TypeCode.Double:
                    result = DbDataReader_GetDouble;
                    break;
                case TypeCode.Single:
                    result = DbDataReader_GetFloat;
                    break;
                case TypeCode.DateTime:
                    result = DbDataReader_GetDateTime;
                    break;
                case TypeCode.Byte:
                    result = DbDataReader_GetByte;
                    break;
                default:
                    if (typeof(Guid) == type)
                    {
                        // Guid doesn't have a type code
                        result = DbDataReader_GetGuid;
                    }
                    else if (typeof(TimeSpan) == type ||
                             typeof(DateTimeOffset) == type)
                    {
                        // TimeSpan and DateTimeOffset don't have a type code or a specific
                        // GetXXX method
                        result = DbDataReader_GetValue;
                    }
                    else if (typeof(Object) == type)
                    {
                        // We assume that Object means we want DBNull rather than null. I believe this is a bug.
                        result = DbDataReader_GetValue;
                    }
                    else
                    {
                        result = DbDataReader_GetValue;
                        isNullable = true;
                    }
                    break;
            }
            return result;
        }
 
        /// <summary>
        /// Visit(VarRefColumnMap)
        /// 
        /// This should throw; VarRefColumnMaps should be removed by the PlanCompiler.
        /// </summary>
        internal override TranslatorResult Visit(VarRefColumnMap columnMap, TranslatorArg arg)
        {
            Debug.Fail("VarRefColumnMap should be substituted at this point");
            throw EntityUtil.InvalidOperation(String.Empty);
        }
 
        #endregion
 
        #endregion
    }
}