translator.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DataEntity / System / Data / Common / internal / materialization / translator.cs / 1 / translator.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
// [....]
//----------------------------------------------------------------------------- 
 
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.ELinq; 
using System.Data.Objects.Internal;
using System.Data.Query.InternalTrees; 
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions; 
using System.Reflection;
using System.Security.Permissions; 
using System.Security; 
using System.Text;
 
namespace System.Data.Common.Internal.Materialization
{
    /// 
    /// Struct containing the requested type and parent column map used 
    /// as the arg in the Translator visitor.
    ///  
    internal struct TranslatorArg 
    {
        internal readonly Type RequestedType; 

        internal TranslatorArg(Type requestedType)
        {
            this.RequestedType = requestedType; 
        }
    } 
 
    /// 
    /// 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.
    /// 
    internal class TranslatorResult 
    {
        private readonly Expression ReturnedExpression; 
        private readonly Type RequestedType; 

        internal TranslatorResult(Expression returnedExpression, Type requestedType) 
        {
            this.RequestedType = requestedType;
            this.ReturnedExpression = returnedExpression;
        } 

        ///  
        /// Return the expression; wrapped with the appropriate cast/convert 
        /// logic to guarantee it's type.
        ///  
        internal Expression Expression
        {
            get
            { 
                Expression result = Translator.Emit_EnsureType(ReturnedExpression, RequestedType);
                return result; 
            } 
        }
    } 

    /// 
    /// 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...
    ///  
    internal class CollectionTranslatorResult : TranslatorResult 
    {
        internal readonly Expression ExpressionToGetCoordinator; 

        internal CollectionTranslatorResult(Expression returnedExpression, ColumnMap columnMap, Type requestedType, Expression expressionToGetCoordinator)
            : base(returnedExpression, requestedType)
        { 
            this.ExpressionToGetCoordinator = expressionToGetCoordinator;
        } 
    } 

    ///  
    /// Translates query ColumnMap into ShaperFactory. Basically, we interpret the
    /// ColumnMap and compile delegates used to materialize results.
    /// 
    internal class Translator : ColumnMapVisitorWithResults 
    {
        #region private state 
 
        /// 
        /// Gets the O-Space Metadata workspace. 
        /// 
        private readonly MetadataWorkspace _workspace;

        ///  
        /// Gets structure telling us how to interpret 'span' rows (includes implicit
        /// relationship span and explicit full span via ObjectQuery.Include(). 
        ///  
        private readonly SpanIndex _spanIndex;
 
        /// 
        /// Gets the MergeOption for the current query (influences our handling of
        /// entities when they are materialized).
        ///  
        private readonly MergeOption _mergeOption;
 
        ///  
        /// When true, indicates we're processing for the value layer (BridgeDataReader)
        /// and not the ObjectMaterializer 
        /// 
        private readonly bool IsValueLayer;

        ///  
        /// Gets scratchpad for topmost nested reader coordinator.
        ///  
        private CoordinatorScratchpad _rootCoordinatorScratchpad; 

        ///  
        /// Gets scratchpad for the coordinator builder for the nested reader currently
        /// being translated or emitted.
        /// 
        private CoordinatorScratchpad _currentCoordinatorScratchpad; 

        ///  
        /// Gets number of 'Shaper.State' slots allocated (used to hold onto intermediate 
        /// values during materialization)
        ///  
        private int _stateSlotCount;

        /// 
        /// Set to true if any Entity/Complex type/property for which we're emitting a 
        /// handler has a security LinkDemand attribute. Used to determine which security
        /// checks are necessary when invoking the delegate. 
        ///  
        private bool _hasLinkDemand;
 
        /// 
        /// 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. 
        /// 
        private bool _hasNonPublicMembers; 
 
        /// 
        /// Keeps track of all LINQ expressions accepted from the user code. 
        /// 
        private readonly List _userExpressions = new List();

        ///  
        /// Local cache of ObjectTypeMappings for EdmTypes (to prevent expensive lookups).
        ///  
        private readonly Dictionary _objectTypeMappings = new Dictionary(); 

        #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
 
        ///  
        /// The main entry point for the translation process. Given a ColumnMap, returns
        /// a ShaperFactory which can be used to materialize results for a query. 
        /// 
        internal static ShaperFactory TranslateColumnMap(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 result; 
            string columnMapKey = ColumnMapKeyBuilder.GetColumnMapKey(columnMap, spanIndex);
            ShaperFactoryQueryCacheKey cacheKey = new ShaperFactoryQueryCacheKey(columnMapKey, mergeOption, valueLayer); 

            if (queryCacheManager.TryCacheLookup(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?
 
            // Before compiling delegates (which asserts the permissions needed to emit 
            // references to non public assembly types) check that user delegates can be
            // compiled in non-elevated context. 
            translator.VerifyUserExpressions();

            // 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 coordinatorFactory = (CoordinatorFactory)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(translator._stateSlotCount, coordinatorFactory, checkPermissionsDelegate, mergeOption); 
            QueryCacheEntry cacheEntry = new ShaperFactoryQueryCacheEntry(cacheKey, result); 
            if (queryCacheManager.TryLookupAndAdd(cacheEntry, out cacheEntry))
            { 
                // Someone beat us to it. Use their result instead.
                result = ((ShaperFactoryQueryCacheEntry)cacheEntry).GetTarget();
            }
            return result; 
        }
 
        ///  
        /// Compiles a delegate taking a Shaper instance and returning values. Used to compile
        /// Expressions produced by the emitter. 
        ///
        /// Asserts MemberAccess to skip visbility check & ReflectionEmit so we can generate
        /// the method.  This means that that security checks are skipped. Before calling this
        /// method you must ensure that you've done a TestComple to ensure the compilation 
        /// doesn't violate them.
        ///  
        [SecurityCritical] 
        [SecurityTreatAsSafe]
        [ReflectionPermission(SecurityAction.Assert, MemberAccess = true, ReflectionEmit = true)] 
        internal static Func Compile(Expression body)
        {
            var lambda = Expression.Lambda>(body, Shaper_Parameter);
            return lambda.Compile(); 
        }
 
        ///  
        /// Non-generic version of Compile (where the result type is passed in as an argument rather
        /// than a type parameter) 
        /// 
        internal static object Compile(Type resultType, Expression body)
        {
            MethodInfo compile = Translator_Compile.MakeGenericMethod(resultType); 
            return compile.Invoke(null, new object[] { body });
        } 
 
        /// 
        /// Tell the translator about a user-defined LINQ expression that is being inlined 
        /// in the materializer delegate.  Before we produce the shaper factory we'll ensure
        /// that security is not violated by using this expression in our delegates.
        /// 
        internal void RegisterUserExpression(Expression expression) 
        {
            _userExpressions.Add(expression); 
        } 

        #endregion 

        #region helpers

        ///  
        /// Allocates a slot in 'Shaper.State' which can be used as storage for
        /// materialization tasks (e.g. remembering key values for a nested collection) 
        ///  
        private int AllocateStateSlot()
        { 
            return _stateSlotCount++;
        }

        ///  
        /// 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.
        ///  
        private Action GetCheckPermissionsDelegate()
        {
            // Emit an action to check runtime permissions.
            Action checkPermissions; 
            if (_hasLinkDemand)
            { 
                checkPermissions = DemandFullTrust; 
            }
            else if (_hasNonPublicMembers) 
            {
                checkPermissions = DemandMemberAccess;
            }
            else 
            {
                checkPermissions = null; 
            } 
            return checkPermissions;
        } 

        private static void DemandFullTrust()
        {
            LightweightCodeGenerator.FullTrustPermission.Demand(); 
        }
 
        private static void DemandMemberAccess() 
        {
            LightweightCodeGenerator.MemberAccessReflectionPermission.Demand(); 
        }

        /// 
        /// 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). 
        ///  
        private void VerifyUserExpressions()
        { 
            foreach (Expression expression in _userExpressions)
            {
                MethodInfo testCompileMethod = Translator_TestCompile.MakeGenericMethod(expression.Type);
                testCompileMethod.Invoke(null, new object[] { expression }); 
            }
        } 
 
        /// 
        /// Compile a user expression to ensure that security will be 
        /// maintained when we build the delegates that call it.
        /// 
        private static void TestCompile(Expression expression)
        { 
            Debug.Assert(expression.Type == typeof(T), "incorrect lambda expresion body type)");
            Expression.Lambda>(expression).Compile(); 
        } 

        ///  
        /// Return the CLR type we're supposed to materialize for the TypeUsage
        /// 
        private Type DetermineClrType(TypeUsage typeUsage)
        { 
            return DetermineClrType(typeUsage.EdmType);
        } 
 
        /// 
        /// Return the CLR type we're supposed to materialize for the EdmType 
        /// 
        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);
                    }
                    else 
                    {
                        EdmType edmElementType = ((CollectionType)edmType).TypeUsage.EdmType; 
                        result = DetermineClrType(edmElementType); 
                        result = typeof(IEnumerable<>).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:
                    throw EntityUtil.UnexpectedMetadataType(edmType);
            }
            Debug.Assert(null != result, "no result?"); // just making sure we cover this in the switch statement. 

            return result; 
        } 

        ///  
        /// Get the ConstructorInfo for the type specified, and ensure we keep track
        /// of any security requirements that the type has.
        /// 
        private ConstructorInfo GetConstructor(Type type) 
        {
            ConstructorInfo result = null; 
            if (!type.IsAbstract) 
            {
                result = LightweightCodeGenerator.GetConstructorForType(type); 

                // remember security requirements for this constructor
                if (LightweightCodeGenerator.HasLinkDemand(result))
                { 
                    _hasLinkDemand = true;
                } 
                if (!LightweightCodeGenerator.IsPublic(result)) 
                {
                    _hasNonPublicMembers = true; 
                }
            }
            return result;
        } 

        ///  
        /// 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). 
        /// 
        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;
        } 
 
        /// 
        /// Remove spanned info from the edmType 
        /// 
        /// 
        /// 
        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;
        } 

        ///  
        /// Creates an expression representing an inline delegate of type Func<Shaper, body.Type> 
        /// 
        private LambdaExpression CreateInlineDelegate(Expression body) 
        {
            // Note that we call through to a typed method so that we can call Expression.Lambda 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> TypedCreateInlineDelegate(Expression body)
        {
            Expression> result = Expression.Lambda>(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).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_HandleEntity = typeof(Shaper).GetMethod("HandleEntity");
        private static readonly MethodInfo Shaper_HandleEntityAppendOnly = typeof(Shaper).GetMethod("HandleEntityAppendOnly");
        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_HandleIEntityWithRelationships = typeof(Shaper).GetMethod("HandleIEntityWithRelationships"); 
        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_TestCompile = typeof(Translator).GetMethod("TestCompile", BindingFlags.NonPublic | BindingFlags.Static);
        private static readonly MethodInfo Translator_TypedCreateInlineDelegate = typeof(Translator).GetMethod("TypedCreateInlineDelegate", BindingFlags.NonPublic | BindingFlags.Instance); 

        #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 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"));
 
        #endregion
 
        ///  
        /// Create expression to AndAlso the expressions and return the result.
        ///  
        private static Expression Emit_AndAlso(IEnumerable operands)
        {
            Expression result = null;
            foreach (Expression operand in operands) 
            {
                if (result == null) 
                { 
                    result = operand;
                } 
                else
                {
                    result = Expression.AndAlso(result, operand);
                } 
            }
            return result; 
        } 

        ///  
        /// Create expression to bitwise-or the expressions and return the result.
        /// 
        private static Expression Emit_BitwiseOr(IEnumerable operands)
        { 
            Expression result = null;
            foreach (Expression operand in operands) 
            { 
                if (result == null)
                { 
                    result = operand;
                }
                else
                { 
                    result = Expression.Or(result, operand);
                } 
            } 
            return result;
        } 

        /// 
        /// 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. 
        /// 
        /// Type of null expression. 
        /// Null expression.
        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; 
        }

        /// 
        /// Create expression that guarantees the input expression is of the specified 
        /// type; no Convert is added if the expression is alread of the same type.
        /// 
        /// Internal because it is called from the TranslatorResult. 
        /// 
        internal static Expression Emit_EnsureType(Expression input, Type type) 
        {
            Expression result = input;
            if (input.Type != 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; 
        }


 

        ///  
        /// Method that the generated expression calls when the types are not 
        /// assignable
        ///  
        private static TTarget CheckedConvert(TSource value)
        {
            checked
            { 
                try
                { 
                    return (TTarget)(object)value; 
                }
                catch (InvalidCastException) 
                {
                    throw EntityUtil.ValueInvalidCast(value.GetType(), typeof(TTarget));
                }
                catch (NullReferenceException) 
                {
                    throw EntityUtil.ValueNullReferenceCast(typeof(TTarget)); 
                } 
            }
        } 

        /// 
        /// Create expression to compare the results of two expressions and return
        /// whether they are equal.  Note we have special case logic for byte arrays. 
        /// 
        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; 
        }

        /// 
        /// 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. 
        ///  
        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;
        }
 
        /// 
        /// 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).
        ///  
        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 keyReaders = new List(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) 
            {
                // 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;
        } 

        ///  
        /// 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.
        ///  
        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;
        } 

        /// 
        /// Create expression to call the specified Get method(ie: GetInt32, GetString, et al)
        /// of the shaper's source data reader 
        /// 
        private static Expression Emit_Reader_GetXXX(int ordinal, Type type, MethodInfo dataReaderMethod) 
        { 
            // (type)shaper.Reader.Get???(ordinal)
            Expression result = Emit_EnsureType(Expression.Call(Shaper_Reader, dataReaderMethod, Expression.Constant(ordinal)), type); 
            return result;
        }

        ///  
        /// Create expression to call the GetValue method of the shaper's source data reader
        ///  
        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;
        }
 
        /// 
        /// Create expression to call the IsDBNull method of the shaper's source data reader 
        ///  
        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;
        } 

        ///  
        /// Create expression to call the IsDBNull method of the shaper's source data reader 
        /// for the scalar column represented by the column map.
        ///  
        private static Expression Emit_Reader_IsDBNull(ColumnMap columnMap)
        {
            //
            Expression result = Emit_Reader_IsDBNull(((ScalarColumnMap)columnMap).ColumnPos); 
            return result;
        } 
 
        /// 
        /// Create expression to read a property value with error handling 
        /// 
        private static Expression Emit_Shaper_GetPropertyValueWithErrorHandling(Type propertyType, int ordinal, string propertyName, string typeName)
        {
            // shaper.GetColumnValueWithErrorHandling(ordinal, propertyName, typeName) 
            Expression result = Expression.Call(Shaper_Parameter, Shaper_GetPropertyValueWithErrorHandling.MakeGenericMethod(propertyType), Expression.Constant(ordinal), Expression.Constant(propertyName), Expression.Constant(typeName));
            return result; 
        } 

        ///  
        /// Create expression to read a column value with error handling
        /// 
        private static Expression Emit_Shaper_GetColumnValueWithErrorHandling(Type columnType, int ordinal)
        { 
            // shaper.GetColumnValueWithErrorHandling(ordinal, propertyName, typeName)
            Expression result = Expression.Call(Shaper_Parameter, Shaper_GetColumnValueWithErrorHandling.MakeGenericMethod(columnType), Expression.Constant(ordinal)); 
            return result; 
        }
 
        /// 
        /// Create expression to read an item from the shaper's state array
        /// 
        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;
        } 

        /// 
        /// Create expression to set an item in the shaper's state array
        ///  
        private static Expression Emit_Shaper_SetState(int stateSlotNumber, Expression value)
        { 
            // shaper.SetState(stateSlotNumber, value) 
            Expression result = Expression.Call(Shaper_Parameter, Shaper_SetState.MakeGenericMethod(value.Type), Expression.Constant(stateSlotNumber), value);
            return result; 
        }

        /// 
        /// Create expression to set an item in the shaper's state array 
        /// 
        private static Expression Emit_Shaper_SetStatePassthrough(int stateSlotNumber, Expression value) 
        { 
            // shaper.SetState(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 
 
        /// 
        /// Visit(ComplexTypeColumnMap) 
        /// 
        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 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);
        }
 
        /// 
        /// Visit(EntityColumnMap) 
        ///  
        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 and the
            // clrType doesn't derive from IEntityWithRelationships 
            //
            // 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 entityType = (EntityType)columnMap.Type.EdmType; 
                Type clrType = DetermineClrType(entityType);
                ConstructorInfo constructor = GetConstructor(clrType);

                // Build expressions to read the property values from the source data 
                // reader and bind them to their target properties
                List propertyBindings = CreatePropertyBindings(columnMap, clrType, entityType.Properties); 
 
                bool isIEntityWithKey = typeof(System.Data.Objects.DataClasses.IEntityWithKey).IsAssignableFrom(clrType);
                bool isIEntityWithRelationships = typeof(System.Data.Objects.DataClasses.IEntityWithRelationships).IsAssignableFrom(clrType); 

                // We only need to add a propertyBinding for the EntityKey when the clrType
                // derives from IEntityWithKey
                if (isIEntityWithKey) 
                {
                    // set key value as we construct the entity 
                    MemberBinding entityKeyMemberBinding = Expression.Bind(IEntityKeyWithKey_EntityKey, entityKeyReader); 
                    propertyBindings.Add(entityKeyMemberBinding);
                } 

                // We have all the property bindings now; go ahead and build the expression to
                // construct the entity and store the property values.  We'll wrap it with more
                // stuff that needs to happen (or not) below. 
                constructEntity = Expression.MemberInit(Expression.New(constructor), propertyBindings);
 
                // Setup the RelationshipManager if needed 
                if (isIEntityWithRelationships)
                { 
                    constructEntity = Expression.Call(Shaper_Parameter, Shaper_HandleIEntityWithRelationships.MakeGenericMethod(clrType),
                                                                                            constructEntity,
                                                                                            entitySetReader
                                                                                            ); 
                }
 
                // If we're tracking, call HandleEntity (or HandleIEntityWithKey or 
                // HandleEntityAppendOnly) as appropriate
                if (MergeOption.NoTracking != _mergeOption) 
                {
                    if (isIEntityWithKey && 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 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
                                                                                            );
                        } 
                    }
                } 
 
                // 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_NullConstant(clrType)
                                            ); 
            } 

            return new TranslatorResult(result, arg.RequestedType); 
        }

        /// 
        /// 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. 
        /// 
        private List CreatePropertyBindings(StructuredColumnMap columnMap, Type clrType, ReadOnlyMetadataCollection properties)
        {
            List result = new List(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.PropertySetterHandle, out propertyAccessor, out propertyType); 
 
                // determine if any security checks are required
                if (LightweightCodeGenerator.HasLinkDemand(propertyAccessor)) 
                {
                    _hasLinkDemand = true;
                }
                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); 
                    _currentCoordinatorScratchpad.AddExpressionWithErrorHandling(valueReader, valueReaderWithErrorHandling);
                }

                MemberBinding binding = Expression.Bind(propertyAccessor, valueReader); 
                result.Add(binding);
            } 
            return result; 
        }
 
        /// 
        /// Visit(SimplePolymorphicColumnMap)
        /// 
        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_NullConstant(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);
        }

        ///  
        /// Visit(MultipleDiscriminatorPolymorphicColumnMap)
        ///  
        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);
        }
 
        /// 
        /// 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. 
        /// 
        private Expression MultipleDiscriminatorPolymorphicColumnMapHelper(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>
            List elementDelegates = new List();
            Type typeDelegatePairType = typeof(KeyValuePair>);
            ConstructorInfo typeDelegatePairConstructor = typeDelegatePairType.GetConstructor(new Type[] { typeof(EntityType), typeof(Func) }); 
            foreach (var typeChoice in columnMap.TypeChoices)
            { 
                Expression typeReader = Emit_EnsureType(AcceptWithMappedType(this, typeChoice.Value, columnMap).Expression, 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; 
        } 

        ///  
        /// Visit(RecordColumnMap)
        /// 
        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

                // 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);
                } 
                else
                {
                    RowType spanRowType = (RowType)columnMap.Type.EdmType;
 
                    if (null != _spanIndex && _spanIndex.HasSpanMap(spanRowType))
                    { 
                        result = HandleSpandexRecord(columnMap, arg, spanRowType); 
                    }
                    else 
                    {
                        result = HandleRegularRecord(columnMap, arg, spanRowType);
                    }
                } 

                // If there is a null sentinel process it accordingly. 
                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); 
        }
 
        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(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;
        } 
 
        /// 
        /// Build expression to materialize LINQ initialization types (anonymous 
        /// types, IGrouping, EntityCollection)
        /// 
        private Expression HandleLinqRecord(RecordColumnMap columnMap, InitializerMetadata initializerMetadata)
        { 
            List propertyReaders = new List(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; 
        }
 
        /// 
        /// Build expression to materialize a data record.
        /// 
        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).Expression; 

                // ((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; 
        }
 
        /// 
        /// Build expression to materialize the spanned information
        /// 
        private Expression HandleSpandexRecord(RecordColumnMap columnMap, TranslatorArg arg, RowType spanRowType) 
        {
            Dictionary 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, Emit_EnsureType(result, arg.RequestedType), 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, Emit_EnsureType(result, arg.RequestedType), spannedResultReader, Expression.Constant(targetMember));
                    }
                    else
                    { 
                        // full span element
                        MethodInfo handleFullSpanElementMethod = Shaper_HandleFullSpanElement.MakeGenericMethod(arg.RequestedType, spannedResultReader.Type); 
                        result = Expression.Call(Shaper_Parameter, handleFullSpanElementMethod, Emit_EnsureType(result, arg.RequestedType), spannedResultReader, Expression.Constant(targetMember)); 
                    }
                } 
            }
            return result;
        }
 
        #endregion
 
        #region collection columns 

        ///  
        /// Visit(SimpleCollectionColumnMap)
        /// 
        internal override TranslatorResult Visit(SimpleCollectionColumnMap columnMap, TranslatorArg arg)
        { 
            return ProcessCollectionColumnMap(columnMap, arg);
        } 
 
        /// 
        /// Visit(DiscriminatedCollectionColumnMap) 
        /// 
        internal override TranslatorResult Visit(DiscriminatedCollectionColumnMap columnMap, TranslatorArg arg)
        {
            return ProcessCollectionColumnMap(columnMap, arg, columnMap.Discriminator, columnMap.DiscriminatorValue); 
        }
 
        ///  
        /// Common code for both Simple and Discrminated Column Maps.
        ///  
        private TranslatorResult ProcessCollectionColumnMap(CollectionColumnMap columnMap, TranslatorArg arg)
        {
            return ProcessCollectionColumnMap(columnMap, arg, null, null);
        } 

        ///  
        /// Common code for both Simple and Discrminated Column Maps. 
        /// 
        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.
            Expression elementReader = elementColumnMap.Accept(this, new TranslatorArg(elementType)).Expression; 

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

                // If any compensation is required (returning IOrderedEnumerable, not
                // just vanilla IEnumerable we must wrap the result with a static class
                // that is of the type expected. 
                if (!arg.RequestedType.IsAssignableFrom(result.Type))
                { 
                    // verify that the type is supported 
                    if (typeof(ObjectQuery).IsAssignableFrom(arg.RequestedType))
                    { 
                        throw EntityUtil.NotSupported(Strings.ELinq_UnsupportedObjectQueryMaterialization);
                    }

                    if (!arg.RequestedType.IsAssignableFrom(typeof(IOrderedQueryable<>).MakeGenericType(elementType)) && 
                        !arg.RequestedType.IsAssignableFrom(typeof(IOrderedEnumerable<>).MakeGenericType(elementType)))
                    { 
                        throw EntityUtil.NotSupported(Strings.Materializer_UnsupportedCollectionType(arg.RequestedType)); 
                    }
 
                    // new CompensatingCollection(_collectionReader)
                    Type compensatingCollectionType = typeof(CompensatingCollection<>).MakeGenericType(elementType);
                    ConstructorInfo constructorInfo = compensatingCollectionType.GetConstructors()[0];
                    result = Emit_EnsureType(Expression.New(constructorInfo, result), compensatingCollectionType); 
                }
            } 
 
            ExitCoodinatorTranslateScope();
            return new CollectionTranslatorResult(result, columnMap, arg.RequestedType, expressionToGetCoordinator); 
        }

        /// 
        /// Returns the CLR Type of the element of the collection 
        /// 
        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("{{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;
        } 

        /// 
        /// Build up the coordinator graph using Enter/ExitCoordinatorTranslateScope.
        ///  
        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 ExitCoodinatorTranslateScope()
        { 
            _currentCoordinatorScratchpad = _currentCoordinatorScratchpad.Parent;
        } 
 
        /// 
        /// 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.
        ///  
        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 = Emit_EnsureType(element, elementType);

            // 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 setKeyTerms = new List(keyReaders.Length); 
            List checkKeyTerms = new List(keyReaders.Length);
 
            foreach (Expression keyReader in keyReaders)
            {
                // allocate space for the key value in the reader state
                int keyStateSlotNumber = AllocateStateSlot(); 

                // SetKey: readerState.SetState(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)readerState.State[stateOrdinal]
            Expression result = Emit_Shaper_GetState(stateSlotNumber, typeof(Coordinator<>).MakeGenericType(elementType)); 
            return result;
        }

        #endregion 

        #region "scalar" columns 
 
        /// 
        /// Visit(RefColumnMap) 
        ///
        /// If the entityKey has a value, then return it otherwise return a null
        /// valued EntityKey.  The EntityKey construction is the tricky part.
        ///  
        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); 
        }
 
        /// 
        /// 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. 
        ///  
        internal override TranslatorResult Visit(ScalarColumnMap columnMap, TranslatorArg arg)
        { 
            Type type = arg.RequestedType;
            int ordinal = columnMap.ColumnPos;
            bool needsNullableCheck;
            MethodInfo readerMethod = GetReaderMethod(type, out needsNullableCheck); 

            Expression result = Emit_Reader_GetXXX(ordinal, type, readerMethod); 
 
            // if type was Nullable, wrap the expression with check for null
            // value and produce the correct typed null instead.  Strings, of 
            // course, can't be Nullable, so we'll always do this.
            if (needsNullableCheck)
            {
                result = Expression.Condition(Emit_Reader_IsDBNull(ordinal), 
                                            Expression.Constant(TypeSystem.GetDefaultValue(arg.RequestedType), arg.RequestedType),
                                            result); 
 
            }
 
            // also create a version of the expression with error handling so that we can throw
            // better exception messages when needed
            Expression resultWithErrorHandling = Emit_Shaper_GetColumnValueWithErrorHandling(arg.RequestedType, ordinal);
            _currentCoordinatorScratchpad.AddExpressionWithErrorHandling(result, resultWithErrorHandling); 

            return new TranslatorResult(result, arg.RequestedType); 
        } 

        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 
            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;
        } 

        ///  
        /// Visit(VarRefColumnMap) 
        ///
        /// This should throw; VarRefColumnMaps should be removed by the PlanCompiler. 
        /// 
        internal override TranslatorResult Visit(VarRefColumnMap columnMap, TranslatorArg arg)
        {
            Debug.Fail("VarRefColumnMap should be substituted at this point"); 
            throw EntityUtil.InvalidOperation(String.Empty);
        } 
 
        #endregion
 
        #endregion
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
// [....]
//----------------------------------------------------------------------------- 
 
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.ELinq; 
using System.Data.Objects.Internal;
using System.Data.Query.InternalTrees; 
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions; 
using System.Reflection;
using System.Security.Permissions; 
using System.Security; 
using System.Text;
 
namespace System.Data.Common.Internal.Materialization
{
    /// 
    /// Struct containing the requested type and parent column map used 
    /// as the arg in the Translator visitor.
    ///  
    internal struct TranslatorArg 
    {
        internal readonly Type RequestedType; 

        internal TranslatorArg(Type requestedType)
        {
            this.RequestedType = requestedType; 
        }
    } 
 
    /// 
    /// 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.
    /// 
    internal class TranslatorResult 
    {
        private readonly Expression ReturnedExpression; 
        private readonly Type RequestedType; 

        internal TranslatorResult(Expression returnedExpression, Type requestedType) 
        {
            this.RequestedType = requestedType;
            this.ReturnedExpression = returnedExpression;
        } 

        ///  
        /// Return the expression; wrapped with the appropriate cast/convert 
        /// logic to guarantee it's type.
        ///  
        internal Expression Expression
        {
            get
            { 
                Expression result = Translator.Emit_EnsureType(ReturnedExpression, RequestedType);
                return result; 
            } 
        }
    } 

    /// 
    /// 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...
    ///  
    internal class CollectionTranslatorResult : TranslatorResult 
    {
        internal readonly Expression ExpressionToGetCoordinator; 

        internal CollectionTranslatorResult(Expression returnedExpression, ColumnMap columnMap, Type requestedType, Expression expressionToGetCoordinator)
            : base(returnedExpression, requestedType)
        { 
            this.ExpressionToGetCoordinator = expressionToGetCoordinator;
        } 
    } 

    ///  
    /// Translates query ColumnMap into ShaperFactory. Basically, we interpret the
    /// ColumnMap and compile delegates used to materialize results.
    /// 
    internal class Translator : ColumnMapVisitorWithResults 
    {
        #region private state 
 
        /// 
        /// Gets the O-Space Metadata workspace. 
        /// 
        private readonly MetadataWorkspace _workspace;

        ///  
        /// Gets structure telling us how to interpret 'span' rows (includes implicit
        /// relationship span and explicit full span via ObjectQuery.Include(). 
        ///  
        private readonly SpanIndex _spanIndex;
 
        /// 
        /// Gets the MergeOption for the current query (influences our handling of
        /// entities when they are materialized).
        ///  
        private readonly MergeOption _mergeOption;
 
        ///  
        /// When true, indicates we're processing for the value layer (BridgeDataReader)
        /// and not the ObjectMaterializer 
        /// 
        private readonly bool IsValueLayer;

        ///  
        /// Gets scratchpad for topmost nested reader coordinator.
        ///  
        private CoordinatorScratchpad _rootCoordinatorScratchpad; 

        ///  
        /// Gets scratchpad for the coordinator builder for the nested reader currently
        /// being translated or emitted.
        /// 
        private CoordinatorScratchpad _currentCoordinatorScratchpad; 

        ///  
        /// Gets number of 'Shaper.State' slots allocated (used to hold onto intermediate 
        /// values during materialization)
        ///  
        private int _stateSlotCount;

        /// 
        /// Set to true if any Entity/Complex type/property for which we're emitting a 
        /// handler has a security LinkDemand attribute. Used to determine which security
        /// checks are necessary when invoking the delegate. 
        ///  
        private bool _hasLinkDemand;
 
        /// 
        /// 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. 
        /// 
        private bool _hasNonPublicMembers; 
 
        /// 
        /// Keeps track of all LINQ expressions accepted from the user code. 
        /// 
        private readonly List _userExpressions = new List();

        ///  
        /// Local cache of ObjectTypeMappings for EdmTypes (to prevent expensive lookups).
        ///  
        private readonly Dictionary _objectTypeMappings = new Dictionary(); 

        #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
 
        ///  
        /// The main entry point for the translation process. Given a ColumnMap, returns
        /// a ShaperFactory which can be used to materialize results for a query. 
        /// 
        internal static ShaperFactory TranslateColumnMap(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 result; 
            string columnMapKey = ColumnMapKeyBuilder.GetColumnMapKey(columnMap, spanIndex);
            ShaperFactoryQueryCacheKey cacheKey = new ShaperFactoryQueryCacheKey(columnMapKey, mergeOption, valueLayer); 

            if (queryCacheManager.TryCacheLookup(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?
 
            // Before compiling delegates (which asserts the permissions needed to emit 
            // references to non public assembly types) check that user delegates can be
            // compiled in non-elevated context. 
            translator.VerifyUserExpressions();

            // 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 coordinatorFactory = (CoordinatorFactory)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(translator._stateSlotCount, coordinatorFactory, checkPermissionsDelegate, mergeOption); 
            QueryCacheEntry cacheEntry = new ShaperFactoryQueryCacheEntry(cacheKey, result); 
            if (queryCacheManager.TryLookupAndAdd(cacheEntry, out cacheEntry))
            { 
                // Someone beat us to it. Use their result instead.
                result = ((ShaperFactoryQueryCacheEntry)cacheEntry).GetTarget();
            }
            return result; 
        }
 
        ///  
        /// Compiles a delegate taking a Shaper instance and returning values. Used to compile
        /// Expressions produced by the emitter. 
        ///
        /// Asserts MemberAccess to skip visbility check & ReflectionEmit so we can generate
        /// the method.  This means that that security checks are skipped. Before calling this
        /// method you must ensure that you've done a TestComple to ensure the compilation 
        /// doesn't violate them.
        ///  
        [SecurityCritical] 
        [SecurityTreatAsSafe]
        [ReflectionPermission(SecurityAction.Assert, MemberAccess = true, ReflectionEmit = true)] 
        internal static Func Compile(Expression body)
        {
            var lambda = Expression.Lambda>(body, Shaper_Parameter);
            return lambda.Compile(); 
        }
 
        ///  
        /// Non-generic version of Compile (where the result type is passed in as an argument rather
        /// than a type parameter) 
        /// 
        internal static object Compile(Type resultType, Expression body)
        {
            MethodInfo compile = Translator_Compile.MakeGenericMethod(resultType); 
            return compile.Invoke(null, new object[] { body });
        } 
 
        /// 
        /// Tell the translator about a user-defined LINQ expression that is being inlined 
        /// in the materializer delegate.  Before we produce the shaper factory we'll ensure
        /// that security is not violated by using this expression in our delegates.
        /// 
        internal void RegisterUserExpression(Expression expression) 
        {
            _userExpressions.Add(expression); 
        } 

        #endregion 

        #region helpers

        ///  
        /// Allocates a slot in 'Shaper.State' which can be used as storage for
        /// materialization tasks (e.g. remembering key values for a nested collection) 
        ///  
        private int AllocateStateSlot()
        { 
            return _stateSlotCount++;
        }

        ///  
        /// 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.
        ///  
        private Action GetCheckPermissionsDelegate()
        {
            // Emit an action to check runtime permissions.
            Action checkPermissions; 
            if (_hasLinkDemand)
            { 
                checkPermissions = DemandFullTrust; 
            }
            else if (_hasNonPublicMembers) 
            {
                checkPermissions = DemandMemberAccess;
            }
            else 
            {
                checkPermissions = null; 
            } 
            return checkPermissions;
        } 

        private static void DemandFullTrust()
        {
            LightweightCodeGenerator.FullTrustPermission.Demand(); 
        }
 
        private static void DemandMemberAccess() 
        {
            LightweightCodeGenerator.MemberAccessReflectionPermission.Demand(); 
        }

        /// 
        /// 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). 
        ///  
        private void VerifyUserExpressions()
        { 
            foreach (Expression expression in _userExpressions)
            {
                MethodInfo testCompileMethod = Translator_TestCompile.MakeGenericMethod(expression.Type);
                testCompileMethod.Invoke(null, new object[] { expression }); 
            }
        } 
 
        /// 
        /// Compile a user expression to ensure that security will be 
        /// maintained when we build the delegates that call it.
        /// 
        private static void TestCompile(Expression expression)
        { 
            Debug.Assert(expression.Type == typeof(T), "incorrect lambda expresion body type)");
            Expression.Lambda>(expression).Compile(); 
        } 

        ///  
        /// Return the CLR type we're supposed to materialize for the TypeUsage
        /// 
        private Type DetermineClrType(TypeUsage typeUsage)
        { 
            return DetermineClrType(typeUsage.EdmType);
        } 
 
        /// 
        /// Return the CLR type we're supposed to materialize for the EdmType 
        /// 
        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);
                    }
                    else 
                    {
                        EdmType edmElementType = ((CollectionType)edmType).TypeUsage.EdmType; 
                        result = DetermineClrType(edmElementType); 
                        result = typeof(IEnumerable<>).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:
                    throw EntityUtil.UnexpectedMetadataType(edmType);
            }
            Debug.Assert(null != result, "no result?"); // just making sure we cover this in the switch statement. 

            return result; 
        } 

        ///  
        /// Get the ConstructorInfo for the type specified, and ensure we keep track
        /// of any security requirements that the type has.
        /// 
        private ConstructorInfo GetConstructor(Type type) 
        {
            ConstructorInfo result = null; 
            if (!type.IsAbstract) 
            {
                result = LightweightCodeGenerator.GetConstructorForType(type); 

                // remember security requirements for this constructor
                if (LightweightCodeGenerator.HasLinkDemand(result))
                { 
                    _hasLinkDemand = true;
                } 
                if (!LightweightCodeGenerator.IsPublic(result)) 
                {
                    _hasNonPublicMembers = true; 
                }
            }
            return result;
        } 

        ///  
        /// 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). 
        /// 
        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;
        } 
 
        /// 
        /// Remove spanned info from the edmType 
        /// 
        /// 
        /// 
        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;
        } 

        ///  
        /// Creates an expression representing an inline delegate of type Func<Shaper, body.Type> 
        /// 
        private LambdaExpression CreateInlineDelegate(Expression body) 
        {
            // Note that we call through to a typed method so that we can call Expression.Lambda 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> TypedCreateInlineDelegate(Expression body)
        {
            Expression> result = Expression.Lambda>(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).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_HandleEntity = typeof(Shaper).GetMethod("HandleEntity");
        private static readonly MethodInfo Shaper_HandleEntityAppendOnly = typeof(Shaper).GetMethod("HandleEntityAppendOnly");
        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_HandleIEntityWithRelationships = typeof(Shaper).GetMethod("HandleIEntityWithRelationships"); 
        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_TestCompile = typeof(Translator).GetMethod("TestCompile", BindingFlags.NonPublic | BindingFlags.Static);
        private static readonly MethodInfo Translator_TypedCreateInlineDelegate = typeof(Translator).GetMethod("TypedCreateInlineDelegate", BindingFlags.NonPublic | BindingFlags.Instance); 

        #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 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"));
 
        #endregion
 
        ///  
        /// Create expression to AndAlso the expressions and return the result.
        ///  
        private static Expression Emit_AndAlso(IEnumerable operands)
        {
            Expression result = null;
            foreach (Expression operand in operands) 
            {
                if (result == null) 
                { 
                    result = operand;
                } 
                else
                {
                    result = Expression.AndAlso(result, operand);
                } 
            }
            return result; 
        } 

        ///  
        /// Create expression to bitwise-or the expressions and return the result.
        /// 
        private static Expression Emit_BitwiseOr(IEnumerable operands)
        { 
            Expression result = null;
            foreach (Expression operand in operands) 
            { 
                if (result == null)
                { 
                    result = operand;
                }
                else
                { 
                    result = Expression.Or(result, operand);
                } 
            } 
            return result;
        } 

        /// 
        /// 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. 
        /// 
        /// Type of null expression. 
        /// Null expression.
        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; 
        }

        /// 
        /// Create expression that guarantees the input expression is of the specified 
        /// type; no Convert is added if the expression is alread of the same type.
        /// 
        /// Internal because it is called from the TranslatorResult. 
        /// 
        internal static Expression Emit_EnsureType(Expression input, Type type) 
        {
            Expression result = input;
            if (input.Type != 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; 
        }


 

        ///  
        /// Method that the generated expression calls when the types are not 
        /// assignable
        ///  
        private static TTarget CheckedConvert(TSource value)
        {
            checked
            { 
                try
                { 
                    return (TTarget)(object)value; 
                }
                catch (InvalidCastException) 
                {
                    throw EntityUtil.ValueInvalidCast(value.GetType(), typeof(TTarget));
                }
                catch (NullReferenceException) 
                {
                    throw EntityUtil.ValueNullReferenceCast(typeof(TTarget)); 
                } 
            }
        } 

        /// 
        /// Create expression to compare the results of two expressions and return
        /// whether they are equal.  Note we have special case logic for byte arrays. 
        /// 
        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; 
        }

        /// 
        /// 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. 
        ///  
        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;
        }
 
        /// 
        /// 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).
        ///  
        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 keyReaders = new List(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) 
            {
                // 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;
        } 

        ///  
        /// 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.
        ///  
        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;
        } 

        /// 
        /// Create expression to call the specified Get method(ie: GetInt32, GetString, et al)
        /// of the shaper's source data reader 
        /// 
        private static Expression Emit_Reader_GetXXX(int ordinal, Type type, MethodInfo dataReaderMethod) 
        { 
            // (type)shaper.Reader.Get???(ordinal)
            Expression result = Emit_EnsureType(Expression.Call(Shaper_Reader, dataReaderMethod, Expression.Constant(ordinal)), type); 
            return result;
        }

        ///  
        /// Create expression to call the GetValue method of the shaper's source data reader
        ///  
        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;
        }
 
        /// 
        /// Create expression to call the IsDBNull method of the shaper's source data reader 
        ///  
        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;
        } 

        ///  
        /// Create expression to call the IsDBNull method of the shaper's source data reader 
        /// for the scalar column represented by the column map.
        ///  
        private static Expression Emit_Reader_IsDBNull(ColumnMap columnMap)
        {
            //
            Expression result = Emit_Reader_IsDBNull(((ScalarColumnMap)columnMap).ColumnPos); 
            return result;
        } 
 
        /// 
        /// Create expression to read a property value with error handling 
        /// 
        private static Expression Emit_Shaper_GetPropertyValueWithErrorHandling(Type propertyType, int ordinal, string propertyName, string typeName)
        {
            // shaper.GetColumnValueWithErrorHandling(ordinal, propertyName, typeName) 
            Expression result = Expression.Call(Shaper_Parameter, Shaper_GetPropertyValueWithErrorHandling.MakeGenericMethod(propertyType), Expression.Constant(ordinal), Expression.Constant(propertyName), Expression.Constant(typeName));
            return result; 
        } 

        ///  
        /// Create expression to read a column value with error handling
        /// 
        private static Expression Emit_Shaper_GetColumnValueWithErrorHandling(Type columnType, int ordinal)
        { 
            // shaper.GetColumnValueWithErrorHandling(ordinal, propertyName, typeName)
            Expression result = Expression.Call(Shaper_Parameter, Shaper_GetColumnValueWithErrorHandling.MakeGenericMethod(columnType), Expression.Constant(ordinal)); 
            return result; 
        }
 
        /// 
        /// Create expression to read an item from the shaper's state array
        /// 
        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;
        } 

        /// 
        /// Create expression to set an item in the shaper's state array
        ///  
        private static Expression Emit_Shaper_SetState(int stateSlotNumber, Expression value)
        { 
            // shaper.SetState(stateSlotNumber, value) 
            Expression result = Expression.Call(Shaper_Parameter, Shaper_SetState.MakeGenericMethod(value.Type), Expression.Constant(stateSlotNumber), value);
            return result; 
        }

        /// 
        /// Create expression to set an item in the shaper's state array 
        /// 
        private static Expression Emit_Shaper_SetStatePassthrough(int stateSlotNumber, Expression value) 
        { 
            // shaper.SetState(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 
 
        /// 
        /// Visit(ComplexTypeColumnMap) 
        /// 
        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 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);
        }
 
        /// 
        /// Visit(EntityColumnMap) 
        ///  
        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 and the
            // clrType doesn't derive from IEntityWithRelationships 
            //
            // 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 entityType = (EntityType)columnMap.Type.EdmType; 
                Type clrType = DetermineClrType(entityType);
                ConstructorInfo constructor = GetConstructor(clrType);

                // Build expressions to read the property values from the source data 
                // reader and bind them to their target properties
                List propertyBindings = CreatePropertyBindings(columnMap, clrType, entityType.Properties); 
 
                bool isIEntityWithKey = typeof(System.Data.Objects.DataClasses.IEntityWithKey).IsAssignableFrom(clrType);
                bool isIEntityWithRelationships = typeof(System.Data.Objects.DataClasses.IEntityWithRelationships).IsAssignableFrom(clrType); 

                // We only need to add a propertyBinding for the EntityKey when the clrType
                // derives from IEntityWithKey
                if (isIEntityWithKey) 
                {
                    // set key value as we construct the entity 
                    MemberBinding entityKeyMemberBinding = Expression.Bind(IEntityKeyWithKey_EntityKey, entityKeyReader); 
                    propertyBindings.Add(entityKeyMemberBinding);
                } 

                // We have all the property bindings now; go ahead and build the expression to
                // construct the entity and store the property values.  We'll wrap it with more
                // stuff that needs to happen (or not) below. 
                constructEntity = Expression.MemberInit(Expression.New(constructor), propertyBindings);
 
                // Setup the RelationshipManager if needed 
                if (isIEntityWithRelationships)
                { 
                    constructEntity = Expression.Call(Shaper_Parameter, Shaper_HandleIEntityWithRelationships.MakeGenericMethod(clrType),
                                                                                            constructEntity,
                                                                                            entitySetReader
                                                                                            ); 
                }
 
                // If we're tracking, call HandleEntity (or HandleIEntityWithKey or 
                // HandleEntityAppendOnly) as appropriate
                if (MergeOption.NoTracking != _mergeOption) 
                {
                    if (isIEntityWithKey && 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 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
                                                                                            );
                        } 
                    }
                } 
 
                // 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_NullConstant(clrType)
                                            ); 
            } 

            return new TranslatorResult(result, arg.RequestedType); 
        }

        /// 
        /// 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. 
        /// 
        private List CreatePropertyBindings(StructuredColumnMap columnMap, Type clrType, ReadOnlyMetadataCollection properties)
        {
            List result = new List(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.PropertySetterHandle, out propertyAccessor, out propertyType); 
 
                // determine if any security checks are required
                if (LightweightCodeGenerator.HasLinkDemand(propertyAccessor)) 
                {
                    _hasLinkDemand = true;
                }
                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); 
                    _currentCoordinatorScratchpad.AddExpressionWithErrorHandling(valueReader, valueReaderWithErrorHandling);
                }

                MemberBinding binding = Expression.Bind(propertyAccessor, valueReader); 
                result.Add(binding);
            } 
            return result; 
        }
 
        /// 
        /// Visit(SimplePolymorphicColumnMap)
        /// 
        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_NullConstant(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);
        }

        ///  
        /// Visit(MultipleDiscriminatorPolymorphicColumnMap)
        ///  
        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);
        }
 
        /// 
        /// 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. 
        /// 
        private Expression MultipleDiscriminatorPolymorphicColumnMapHelper(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>
            List elementDelegates = new List();
            Type typeDelegatePairType = typeof(KeyValuePair>);
            ConstructorInfo typeDelegatePairConstructor = typeDelegatePairType.GetConstructor(new Type[] { typeof(EntityType), typeof(Func) }); 
            foreach (var typeChoice in columnMap.TypeChoices)
            { 
                Expression typeReader = Emit_EnsureType(AcceptWithMappedType(this, typeChoice.Value, columnMap).Expression, 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; 
        } 

        ///  
        /// Visit(RecordColumnMap)
        /// 
        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

                // 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);
                } 
                else
                {
                    RowType spanRowType = (RowType)columnMap.Type.EdmType;
 
                    if (null != _spanIndex && _spanIndex.HasSpanMap(spanRowType))
                    { 
                        result = HandleSpandexRecord(columnMap, arg, spanRowType); 
                    }
                    else 
                    {
                        result = HandleRegularRecord(columnMap, arg, spanRowType);
                    }
                } 

                // If there is a null sentinel process it accordingly. 
                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); 
        }
 
        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(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;
        } 
 
        /// 
        /// Build expression to materialize LINQ initialization types (anonymous 
        /// types, IGrouping, EntityCollection)
        /// 
        private Expression HandleLinqRecord(RecordColumnMap columnMap, InitializerMetadata initializerMetadata)
        { 
            List propertyReaders = new List(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; 
        }
 
        /// 
        /// Build expression to materialize a data record.
        /// 
        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).Expression; 

                // ((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; 
        }
 
        /// 
        /// Build expression to materialize the spanned information
        /// 
        private Expression HandleSpandexRecord(RecordColumnMap columnMap, TranslatorArg arg, RowType spanRowType) 
        {
            Dictionary 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, Emit_EnsureType(result, arg.RequestedType), 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, Emit_EnsureType(result, arg.RequestedType), spannedResultReader, Expression.Constant(targetMember));
                    }
                    else
                    { 
                        // full span element
                        MethodInfo handleFullSpanElementMethod = Shaper_HandleFullSpanElement.MakeGenericMethod(arg.RequestedType, spannedResultReader.Type); 
                        result = Expression.Call(Shaper_Parameter, handleFullSpanElementMethod, Emit_EnsureType(result, arg.RequestedType), spannedResultReader, Expression.Constant(targetMember)); 
                    }
                } 
            }
            return result;
        }
 
        #endregion
 
        #region collection columns 

        ///  
        /// Visit(SimpleCollectionColumnMap)
        /// 
        internal override TranslatorResult Visit(SimpleCollectionColumnMap columnMap, TranslatorArg arg)
        { 
            return ProcessCollectionColumnMap(columnMap, arg);
        } 
 
        /// 
        /// Visit(DiscriminatedCollectionColumnMap) 
        /// 
        internal override TranslatorResult Visit(DiscriminatedCollectionColumnMap columnMap, TranslatorArg arg)
        {
            return ProcessCollectionColumnMap(columnMap, arg, columnMap.Discriminator, columnMap.DiscriminatorValue); 
        }
 
        ///  
        /// Common code for both Simple and Discrminated Column Maps.
        ///  
        private TranslatorResult ProcessCollectionColumnMap(CollectionColumnMap columnMap, TranslatorArg arg)
        {
            return ProcessCollectionColumnMap(columnMap, arg, null, null);
        } 

        ///  
        /// Common code for both Simple and Discrminated Column Maps. 
        /// 
        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.
            Expression elementReader = elementColumnMap.Accept(this, new TranslatorArg(elementType)).Expression; 

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

                // If any compensation is required (returning IOrderedEnumerable, not
                // just vanilla IEnumerable we must wrap the result with a static class
                // that is of the type expected. 
                if (!arg.RequestedType.IsAssignableFrom(result.Type))
                { 
                    // verify that the type is supported 
                    if (typeof(ObjectQuery).IsAssignableFrom(arg.RequestedType))
                    { 
                        throw EntityUtil.NotSupported(Strings.ELinq_UnsupportedObjectQueryMaterialization);
                    }

                    if (!arg.RequestedType.IsAssignableFrom(typeof(IOrderedQueryable<>).MakeGenericType(elementType)) && 
                        !arg.RequestedType.IsAssignableFrom(typeof(IOrderedEnumerable<>).MakeGenericType(elementType)))
                    { 
                        throw EntityUtil.NotSupported(Strings.Materializer_UnsupportedCollectionType(arg.RequestedType)); 
                    }
 
                    // new CompensatingCollection(_collectionReader)
                    Type compensatingCollectionType = typeof(CompensatingCollection<>).MakeGenericType(elementType);
                    ConstructorInfo constructorInfo = compensatingCollectionType.GetConstructors()[0];
                    result = Emit_EnsureType(Expression.New(constructorInfo, result), compensatingCollectionType); 
                }
            } 
 
            ExitCoodinatorTranslateScope();
            return new CollectionTranslatorResult(result, columnMap, arg.RequestedType, expressionToGetCoordinator); 
        }

        /// 
        /// Returns the CLR Type of the element of the collection 
        /// 
        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("{{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;
        } 

        /// 
        /// Build up the coordinator graph using Enter/ExitCoordinatorTranslateScope.
        ///  
        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 ExitCoodinatorTranslateScope()
        { 
            _currentCoordinatorScratchpad = _currentCoordinatorScratchpad.Parent;
        } 
 
        /// 
        /// 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.
        ///  
        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 = Emit_EnsureType(element, elementType);

            // 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 setKeyTerms = new List(keyReaders.Length); 
            List checkKeyTerms = new List(keyReaders.Length);
 
            foreach (Expression keyReader in keyReaders)
            {
                // allocate space for the key value in the reader state
                int keyStateSlotNumber = AllocateStateSlot(); 

                // SetKey: readerState.SetState(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)readerState.State[stateOrdinal]
            Expression result = Emit_Shaper_GetState(stateSlotNumber, typeof(Coordinator<>).MakeGenericType(elementType)); 
            return result;
        }

        #endregion 

        #region "scalar" columns 
 
        /// 
        /// Visit(RefColumnMap) 
        ///
        /// If the entityKey has a value, then return it otherwise return a null
        /// valued EntityKey.  The EntityKey construction is the tricky part.
        ///  
        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); 
        }
 
        /// 
        /// 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. 
        ///  
        internal override TranslatorResult Visit(ScalarColumnMap columnMap, TranslatorArg arg)
        { 
            Type type = arg.RequestedType;
            int ordinal = columnMap.ColumnPos;
            bool needsNullableCheck;
            MethodInfo readerMethod = GetReaderMethod(type, out needsNullableCheck); 

            Expression result = Emit_Reader_GetXXX(ordinal, type, readerMethod); 
 
            // if type was Nullable, wrap the expression with check for null
            // value and produce the correct typed null instead.  Strings, of 
            // course, can't be Nullable, so we'll always do this.
            if (needsNullableCheck)
            {
                result = Expression.Condition(Emit_Reader_IsDBNull(ordinal), 
                                            Expression.Constant(TypeSystem.GetDefaultValue(arg.RequestedType), arg.RequestedType),
                                            result); 
 
            }
 
            // also create a version of the expression with error handling so that we can throw
            // better exception messages when needed
            Expression resultWithErrorHandling = Emit_Shaper_GetColumnValueWithErrorHandling(arg.RequestedType, ordinal);
            _currentCoordinatorScratchpad.AddExpressionWithErrorHandling(result, resultWithErrorHandling); 

            return new TranslatorResult(result, arg.RequestedType); 
        } 

        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 
            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;
        } 

        ///  
        /// Visit(VarRefColumnMap) 
        ///
        /// This should throw; VarRefColumnMaps should be removed by the PlanCompiler. 
        /// 
        internal override TranslatorResult Visit(VarRefColumnMap columnMap, TranslatorArg arg)
        {
            Debug.Fail("VarRefColumnMap should be substituted at this point"); 
            throw EntityUtil.InvalidOperation(String.Empty);
        } 
 
        #endregion
 
        #endregion
    }
}

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

                        

                        

Link Menu

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