ColumnMap.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / ndp / fx / src / DataEntity / System / Data / Query / InternalTrees / ColumnMap.cs / 2 / ColumnMap.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....], [....]
//--------------------------------------------------------------------- 
 
using System;
using System.Text; 
using System.Collections.Generic;
using md = System.Data.Metadata.Edm;
using mp = System.Data.Mapping;
using System.Globalization; 
using System.Diagnostics;
using System.Data.Common.Utils; 
 
// A ColumnMap is a data structure that maps columns from the C space to
// the corresponding columns from one or more underlying readers. 
//
// ColumnMaps are used by the ResultAssembly phase to assemble results in the
// desired shape (as requested by the caller) from a set of underlying
// (usually) flat readers. ColumnMaps are produced as part of the PlanCompiler 
// module of the bridge, and are consumed by the Execution phase of the bridge.
// 
// * Simple (scalar) columns (and UDTs) are represented by a SimpleColumnMap 
// * Record type columns are represented by a RecordColumnMap
// * A nominal type instance (that supports inheritance) is usually represented 
//     by a PolymorphicColumnMap - this polymorphicColumnMap contains information
//     about the type discriminator (assumed to be a simple column), and a mapping
//     from type-discriminator value to the column map for the specific type
// * The specific type for nominal types is represented by ComplexTypeColumnMap 
//     for complextype columns, and EntityColumnMap for entity type columns.
//     EntityColumnMaps additionally have an EntityIdentity that describes 
//     the entity identity. The entity identity is logically just a set of keys 
//     (and the column maps), plus a column map that helps to identify the
//     the appropriate entity set for the entity instance 
// * Refs are represented by a RefColumnMap. The RefColumnMap simply contains an
//   EntityIdentity
// * Collections are represented by either a SimpleCollectionColumnMap or a
//     DiscriminatedCollectionColumnMap. Both of these contain a column map for the 
//     element type, and an optional list of simple columns (the keys) that help
//     demarcate the elements of a specific collection instance. 
//     The DiscriminatedCollectionColumnMap is used in scenarios when the containing 
//     row has multiple collections, and the different collection properties must be
//     differentiated. This differentiation is achieved via a Discriminator column 
//     (a simple column), and a Discriminator value. The value of the Discriminator
//     column is read and compared with the DiscriminatorValue stored in this map
//     to determine if we're dealing with the current collection.
// 
// NOTE:
//  * Key columns are assumed to be SimpleColumns. There may be more than one key 
//      column (applies to EntityColumnMap and *CollectionColumnMap) 
//  * TypeDiscriminator and Discriminator columns are also considered to be
//      SimpleColumns. There are singleton columns. 
//
// It is the responsibility of the PlanCompiler phase to produce the right column
// maps.
// 
// The result of a query is always assumed to be a collection. The ColumnMap that we
// return as part of plan compilation refers to the element type of this collection 
// - the element type is usually a structured type, but may also be a simple type 
//   or another collection type. How does the DbRecord framework handle these cases?
// 
//
namespace System.Data.Query.InternalTrees
{
    ///  
    /// Represents a column
    ///  
    internal abstract class ColumnMap 
    {
        private md.TypeUsage m_type; // column datatype 
        private string m_name; // name of the column

        /// 
        /// Default Column Name; should not be set until CodeGen once we're done 
        /// with all our transformations that might give us a good name, but put
        /// here for ease of finding it. 
        ///  
        internal const string DefaultColumnName = "Value";
 
        /// 
        /// Simple constructor - just needs the name and type of the column
        /// 
        /// column type 
        /// column name
        internal ColumnMap(md.TypeUsage type, string name) 
        { 
            Debug.Assert(type != null, "Unspecified type");
            m_type = type; 
            m_name = name;
        }

        ///  
        /// Get the column's datatype
        ///  
        internal md.TypeUsage Type { get { return m_type; } } 

        ///  
        /// Get the column name
        /// 
        internal string Name
        { 
            get { return m_name; }
            set 
            { 
                Debug.Assert(!String.IsNullOrEmpty(value), "invalid name?");
                m_name = value; 
            }
        }

        ///  
        /// Returns whether the column already has a name;
        ///  
        internal bool IsNamed 
        {
            get { return m_name != null; } 
        }

        /// 
        /// Visitor Design Pattern 
        /// 
        ///  
        ///  
        /// 
        ///  
        [DebuggerNonUserCode]
        internal abstract void Accept(ColumnMapVisitor visitor, TArgType arg);

        ///  
        /// Visitor Design Pattern
        ///  
        ///  
        /// 
        ///  
        /// 
        /// 
        [DebuggerNonUserCode]
        internal abstract TResultType Accept(ColumnMapVisitorWithResults visitor, TArgType arg); 
    }
 
    ///  
    /// Base class for simple column maps; can be either a VarRefColumnMap or
    /// ScalarColumnMap; the former is used pretty much throughout the PlanCompiler, 
    /// while the latter will only be used once we generate the final Plan.
    /// 
    internal abstract class SimpleColumnMap : ColumnMap
    { 
        /// 
        /// Basic constructor 
        ///  
        /// datatype for this column
        /// column name 
        internal SimpleColumnMap(md.TypeUsage type, string name)
            : base(type, name)
        {
        } 
    }
 
    ///  
    /// Column map for a scalar column - maps 1-1 with a column from a
    /// row of the underlying reader 
    /// 
    internal class ScalarColumnMap : SimpleColumnMap
    {
        private int m_commandId; 
        private int m_columnPos;
 
        ///  
        /// Basic constructor
        ///  
        /// datatype for this column
        /// column name
        /// Underlying command to locate this column
        /// Position in underlying reader 
        internal ScalarColumnMap(md.TypeUsage type, string name, int commandId, int columnPos)
            : base(type, name) 
        { 
            Debug.Assert(commandId >= 0, "invalid command id");
            Debug.Assert(columnPos >= 0, "invalid column position"); 
            m_commandId = commandId;
            m_columnPos = columnPos;
        }
 
        /// 
        /// The command (reader, really) to get this column value from 
        ///  
        internal int CommandId { get { return m_commandId; } }
        ///  
        /// Column position within the reader of the command
        /// 
        internal int ColumnPos { get { return m_columnPos; } }
 
        /// 
        /// Visitor Design Pattern 
        ///  
        /// 
        ///  
        /// 
        [DebuggerNonUserCode]
        internal override void Accept(ColumnMapVisitor visitor, TArgType arg)
        { 
            visitor.Visit(this, arg);
        } 
 
        /// 
        /// Visitor Design Pattern 
        /// 
        /// 
        /// 
        ///  
        /// 
        [DebuggerNonUserCode] 
        internal override TResultType Accept(ColumnMapVisitorWithResults visitor, TArgType arg) 
        {
            return visitor.Visit(this, arg); 
        }

        /// 
        /// Debugging support 
        /// 
        ///  
        public override string ToString() 
        {
            return String.Format(CultureInfo.InvariantCulture, "S({0},{1})", this.CommandId, this.ColumnPos); 
        }
    }

    #region Structured Columns 
    /// 
    /// Represents a column map for a structured column 
    ///  
    internal abstract class StructuredColumnMap : ColumnMap
    { 
        private readonly ColumnMap[] m_properties;

        /// 
        /// Structured columnmap constructor 
        /// 
        /// datatype for this column 
        /// column name 
        /// list of properties
        internal StructuredColumnMap(md.TypeUsage type, string name, ColumnMap[] properties) 
            : base(type, name)
        {
            Debug.Assert(properties != null, "No properties (gasp!) for a structured type");
            m_properties = properties; 
        }
 
        ///  
        /// Get the null sentinel column, if any.  Virtual so only derived column map
        /// types that can have NullSentinel have to provide storage, etc. 
        /// 
        virtual internal SimpleColumnMap NullSentinel { get { return null; } }

        ///  
        /// Get the list of properties that constitute this structured type
        ///  
        internal ColumnMap[] Properties { get { return m_properties; } } 

        ///  
        /// Debugging support
        /// 
        /// 
        public override string ToString() 
        {
            StringBuilder sb = new StringBuilder(); 
            string separator = String.Empty; 
            sb.Append("{");
            foreach (ColumnMap c in this.Properties) 
            {
                sb.AppendFormat(CultureInfo.InvariantCulture, "{0}{1}", separator, c);
                separator = ",";
            } 
            sb.Append("}");
            return sb.ToString(); 
        } 
    }
 
    /// 
    /// Represents a record (an untyped structured column)
    /// 
    internal class RecordColumnMap : StructuredColumnMap 
    {
        private SimpleColumnMap m_nullSentinel; 
 
        /// 
        /// Constructor for a record column map 
        /// 
        /// Datatype of this column
        /// column name
        /// List of ColumnMaps - one for each property 
        internal RecordColumnMap(md.TypeUsage type, string name, ColumnMap[] properties, SimpleColumnMap nullSentinel)
            : base(type, name, properties) 
        { 
            m_nullSentinel = nullSentinel;
        } 

        /// 
        /// Get the type Nullability column
        ///  
        internal override SimpleColumnMap NullSentinel { get { return m_nullSentinel; } }
 
        ///  
        /// Visitor Design Pattern
        ///  
        /// 
        /// 
        /// 
        [DebuggerNonUserCode] 
        internal override void Accept(ColumnMapVisitor visitor, TArgType arg)
        { 
            visitor.Visit(this, arg); 
        }
 
        /// 
        /// Visitor Design Pattern
        /// 
        ///  
        /// 
        ///  
        ///  
        [DebuggerNonUserCode]
        internal override TResultType Accept(ColumnMapVisitorWithResults visitor, TArgType arg) 
        {
            return visitor.Visit(this, arg);
        }
    } 

    ///  
    /// Column map for a "typed" column 
    /// - either an entity type or a complex type
    ///  
    internal abstract class TypedColumnMap : StructuredColumnMap
    {
        /// 
        /// Typed columnMap constructor 
        /// 
        /// Datatype of column 
        /// column name 
        /// List of column maps - one for each property
        internal TypedColumnMap(md.TypeUsage type, string name, ColumnMap[] properties) 
            : base(type, name, properties) { }
    }

    ///  
    /// Represents a polymorphic typed column - either an entity or
    /// a complex type. 
    ///  
    internal class SimplePolymorphicColumnMap : TypedColumnMap
    { 
        private SimpleColumnMap m_typeDiscriminator;
        private Dictionary m_typedColumnMap;

        ///  
        /// Internal constructor
        ///  
        /// datatype of the column 
        /// column name
        /// column map for type discriminator column 
        /// base list of fields common to all types
        /// map from type discriminator value->columnMap
        internal SimplePolymorphicColumnMap(md.TypeUsage type,
            string name, 
            ColumnMap[] baseTypeColumns,
            SimpleColumnMap typeDiscriminator, 
            Dictionary typeChoices) 
            : base(type, name, baseTypeColumns)
        { 
            Debug.Assert(typeDiscriminator != null, "Must specify a type discriminator column");
            Debug.Assert(typeChoices != null, "No type choices for polymorphic column");
            m_typedColumnMap = typeChoices;
            m_typeDiscriminator = typeDiscriminator; 
        }
 
        ///  
        /// Get the type discriminator column
        ///  
        internal SimpleColumnMap TypeDiscriminator { get { return m_typeDiscriminator; } }

        /// 
        /// Get the type mapping 
        /// 
        internal Dictionary TypeChoices 
        { 
            get { return m_typedColumnMap; }
        } 

        /// 
        /// Visitor Design Pattern
        ///  
        /// 
        ///  
        ///  
        [DebuggerNonUserCode]
        internal override void Accept(ColumnMapVisitor visitor, TArgType arg) 
        {
            visitor.Visit(this, arg);
        }
 
        /// 
        /// Visitor Design Pattern 
        ///  
        /// 
        ///  
        /// 
        /// 
        [DebuggerNonUserCode]
        internal override TResultType Accept(ColumnMapVisitorWithResults visitor, TArgType arg) 
        {
            return visitor.Visit(this, arg); 
        } 

        ///  
        /// Debugging support
        /// 
        /// 
        public override string ToString() 
        {
            StringBuilder sb = new StringBuilder(); 
            string separator = String.Empty; 

            sb.AppendFormat(CultureInfo.InvariantCulture, "P{{TypeId={0}, ", this.TypeDiscriminator); 
            foreach (KeyValuePair kv in this.TypeChoices)
            {
                sb.AppendFormat(CultureInfo.InvariantCulture, "{0}({1},{2})", separator, kv.Key, kv.Value);
                separator = ","; 
            }
            sb.Append("}"); 
            return sb.ToString(); 
        }
    } 

    /// 
    /// Represents a function import column map.
    ///  
    internal class MultipleDiscriminatorPolymorphicColumnMap : TypedColumnMap
    { 
        private readonly SimpleColumnMap[] m_typeDiscriminators; 
        private readonly Dictionary m_typeChoices;
        private readonly Func m_discriminate; 

        /// 
        /// Internal constructor
        ///  
        internal MultipleDiscriminatorPolymorphicColumnMap(md.TypeUsage type,
            string name, 
            ColumnMap[] baseTypeColumns, 
            SimpleColumnMap[] typeDiscriminators,
            Dictionary typeChoices, 
            Func discriminate)
            : base(type, name, baseTypeColumns)
        {
            Debug.Assert(typeDiscriminators != null, "Must specify type discriminator columns"); 
            Debug.Assert(typeChoices != null, "No type choices for polymorphic column");
            Debug.Assert(discriminate != null, "Must specify discriminate"); 
 
            m_typeDiscriminators = typeDiscriminators;
            m_typeChoices = typeChoices; 
            m_discriminate = discriminate;
        }

        ///  
        /// Get the type discriminator column
        ///  
        internal SimpleColumnMap[] TypeDiscriminators { get { return m_typeDiscriminators; } } 

        ///  
        /// Get the type mapping
        /// 
        internal Dictionary TypeChoices
        { 
            get { return m_typeChoices; }
        } 
 
        /// 
        /// Gets discriminator delegate 
        /// 
        internal Func Discriminate
        {
            get { return m_discriminate; } 
        }
 
        ///  
        /// Visitor Design Pattern
        ///  
        [DebuggerNonUserCode]
        internal override void Accept(ColumnMapVisitor visitor, TArgType arg)
        {
            visitor.Visit(this, arg); 
        }
 
        ///  
        /// Visitor Design Pattern
        ///  
        [DebuggerNonUserCode]
        internal override TResultType Accept(ColumnMapVisitorWithResults visitor, TArgType arg)
        {
            return visitor.Visit(this, arg); 
        }
 
        ///  
        /// Debugging support
        ///  
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            string separator = String.Empty; 

            sb.AppendFormat(CultureInfo.InvariantCulture, "P{{TypeId=<{0}>, ", StringUtil.ToCommaSeparatedString(this.TypeDiscriminators)); 
            foreach (var kv in this.TypeChoices) 
            {
                sb.AppendFormat(CultureInfo.InvariantCulture, "{0}(<{1}>,{2})", separator, kv.Key, kv.Value); 
                separator = ",";
            }
            sb.Append("}");
            return sb.ToString(); 
        }
    } 
 
    /// 
    /// Represents a column map for a specific complextype 
    /// 
    internal class ComplexTypeColumnMap : TypedColumnMap
    {
        private SimpleColumnMap m_nullSentinel; 

        ///  
        /// Constructor 
        /// 
        /// column Datatype 
        /// column name
        /// list of properties
        internal ComplexTypeColumnMap(md.TypeUsage type, string name, ColumnMap[] properties, SimpleColumnMap nullSentinel)
            : base(type, name, properties) 
        {
            m_nullSentinel = nullSentinel; 
        } 

        ///  
        /// Get the type Nullability column
        /// 
        internal override SimpleColumnMap NullSentinel { get { return m_nullSentinel; } }
 
        /// 
        /// Visitor Design Pattern 
        ///  
        /// 
        ///  
        /// 
        [DebuggerNonUserCode]
        internal override void Accept(ColumnMapVisitor visitor, TArgType arg)
        { 
            visitor.Visit(this, arg);
        } 
 
        /// 
        /// Visitor Design Pattern 
        /// 
        /// 
        /// 
        ///  
        /// 
        [DebuggerNonUserCode] 
        internal override TResultType Accept(ColumnMapVisitorWithResults visitor, TArgType arg) 
        {
            return visitor.Visit(this, arg); 
        }

        /// 
        /// Debugging support 
        /// 
        ///  
        public override string ToString() 
        {
            string str = String.Format(CultureInfo.InvariantCulture, "C{0}", base.ToString()); 
            return str;
        }

    } 

    ///  
    /// Represents a column map for a specific entity type 
    /// 
    internal class EntityColumnMap : TypedColumnMap 
    {
        private EntityIdentity m_entityIdentity;

        ///  
        /// constructor
        ///  
        /// column datatype 
        /// column name
        /// entity identity information 
        /// list of properties
        internal EntityColumnMap(md.TypeUsage type, string name, ColumnMap[] properties, EntityIdentity entityIdentity)
            : base(type, name, properties)
        { 
            Debug.Assert(entityIdentity != null, "Must specify an entity identity");
            m_entityIdentity = entityIdentity; 
        } 

        ///  
        /// Get the entity identity information
        /// 
        internal EntityIdentity EntityIdentity { get { return m_entityIdentity; } }
 
        /// 
        /// Visitor Design Pattern 
        ///  
        /// 
        ///  
        /// 
        [DebuggerNonUserCode]
        internal override void Accept(ColumnMapVisitor visitor, TArgType arg)
        { 
            visitor.Visit(this, arg);
        } 
 
        /// 
        /// Visitor Design Pattern 
        /// 
        /// 
        /// 
        ///  
        /// 
        [DebuggerNonUserCode] 
        internal override TResultType Accept(ColumnMapVisitorWithResults visitor, TArgType arg) 
        {
            return visitor.Visit(this, arg); 
        }

        /// 
        /// Debugging support 
        /// 
        ///  
        public override string ToString() 
        {
            string str = String.Format(CultureInfo.InvariantCulture, "E{0}", base.ToString()); 
            return str;
        }
    }
 
    /// 
    /// A column map that represents a ref column. 
    ///  
    internal class RefColumnMap: ColumnMap
    { 
        private EntityIdentity m_entityIdentity;

        /// 
        /// Constructor for a ref column 
        /// 
        /// column datatype 
        /// column name 
        /// identity information for this entity
        internal RefColumnMap(md.TypeUsage type, string name, 
            EntityIdentity entityIdentity)
            : base(type, name)
        {
            Debug.Assert(entityIdentity != null, "Must specify entity identity information"); 
            m_entityIdentity = entityIdentity;
        } 
 
        /// 
        /// Get the entity identity information for this ref 
        /// 
        internal EntityIdentity EntityIdentity { get { return m_entityIdentity; } }

        ///  
        /// Visitor Design Pattern
        ///  
        ///  
        /// 
        ///  
        [DebuggerNonUserCode]
        internal override void Accept(ColumnMapVisitor visitor, TArgType arg)
        {
            visitor.Visit(this, arg); 
        }
 
        ///  
        /// Visitor Design Pattern
        ///  
        /// 
        /// 
        /// 
        ///  
        [DebuggerNonUserCode]
        internal override TResultType Accept(ColumnMapVisitorWithResults visitor, TArgType arg) 
        { 
            return visitor.Visit(this, arg);
        } 
    }
    #endregion

    #region Collections 
    /// 
    /// Represents a column map for a collection column. 
    /// The "element" represents the element of the collection - usually a Structured 
    /// type, but occasionally a collection/simple type as well.
    /// The "ForeignKeys" property is optional (but usually necessary) to determine the 
    /// elements of the collection.
    /// 
    internal abstract class CollectionColumnMap : ColumnMap
    { 
        private readonly ColumnMap m_element;
        private readonly SimpleColumnMap[] m_foreignKeys; 
        private readonly SimpleColumnMap[] m_keys; 
        private readonly SortKeyInfo[] m_sortKeys;
 
        /// 
        /// Constructor
        /// 
        /// datatype of column 
        /// column name
        /// column map for collection element 
        /// List of keys 
        /// List of foreign keys
        /// List of sort keys 
        internal CollectionColumnMap(md.TypeUsage type, string name, ColumnMap elementMap, SimpleColumnMap[] keys, SimpleColumnMap[] foreignKeys, SortKeyInfo[] sortKeys)
            : base(type, name)
        {
            Debug.Assert(elementMap != null, "Must specify column map for element"); 

            m_element = elementMap; 
            m_keys = keys ?? new SimpleColumnMap[0]; 
            m_foreignKeys = foreignKeys ?? new SimpleColumnMap[0];
            m_sortKeys = sortKeys ?? new SortKeyInfo[0]; 
        }

        /// 
        /// Get the list of columns that may comprise the foreign key 
        /// 
        internal SimpleColumnMap[] ForeignKeys 
        { 
            get { return m_foreignKeys; }
        } 

        /// 
        /// Get the list of columns that may comprise the key
        ///  
        internal SimpleColumnMap[] Keys
        { 
            get { return m_keys; } 
        }
 
        /// 
        /// Get the list of sort columns
        /// 
        internal SortKeyInfo[] SortKeys 
        {
            get { return m_sortKeys; } 
        } 

        ///  
        /// Get the column map describing the collection element
        /// 
        internal ColumnMap Element
        { 
            get { return m_element; }
        } 
    } 

    ///  
    /// Represents a "simple" collection map.
    /// 
    internal class SimpleCollectionColumnMap : CollectionColumnMap
    { 
        /// 
        /// Basic constructor 
        ///  
        /// Column datatype
        /// column name 
        /// column map for the element of the collection
        /// list of key columns
        /// list of foreign key columns
        /// list of sort key columns 
        internal SimpleCollectionColumnMap(md.TypeUsage type, string name,
            ColumnMap elementMap, 
            SimpleColumnMap[] keys, 
            SimpleColumnMap[] foreignKeys,
            SortKeyInfo[] sortKeys) 
            : base(type, name, elementMap, keys, foreignKeys, sortKeys) { }

        /// 
        /// Visitor Design Pattern 
        /// 
        ///  
        ///  
        /// 
        [DebuggerNonUserCode] 
        internal override void Accept(ColumnMapVisitor visitor, TArgType arg)
        {
            visitor.Visit(this, arg);
        } 

        ///  
        /// Visitor Design Pattern 
        /// 
        ///  
        /// 
        /// 
        /// 
        [DebuggerNonUserCode] 
        internal override TResultType Accept(ColumnMapVisitorWithResults visitor, TArgType arg)
        { 
            return visitor.Visit(this, arg); 
        }
    } 

    /// 
    /// Represents a "discriminated" collection column.
    /// This represents a scenario when multiple collections are represented 
    /// at the same level of the container row, and there is a need to distinguish
    /// between these collections 
    ///  
    internal class DiscriminatedCollectionColumnMap : CollectionColumnMap
    { 
        private SimpleColumnMap m_discriminator;
        private object m_discriminatorValue;

        ///  
        /// Internal constructor
        ///  
        /// Column datatype 
        /// column name
        /// column map for collection element 
        /// Keys for the collection
        /// Foreign keys for the collection
        /// Sort keys for the collection
        /// Discriminator column map 
        /// Discriminator value
        internal DiscriminatedCollectionColumnMap(md.TypeUsage type, string name, 
            ColumnMap elementMap, 
            SimpleColumnMap[] keys,
            SimpleColumnMap[] foreignKeys, 
            SortKeyInfo[] sortKeys,
            SimpleColumnMap discriminator,
            object discriminatorValue)
            : base(type, name, elementMap, keys, foreignKeys, sortKeys) 
        {
            Debug.Assert(discriminator != null, "Must specify a column map for the collection discriminator"); 
            Debug.Assert(discriminatorValue != null, "Must specify a discriminator value"); 
            m_discriminator = discriminator;
            m_discriminatorValue = discriminatorValue; 
        }

        /// 
        /// Get the column that describes the discriminator 
        /// 
        internal SimpleColumnMap Discriminator { get { return m_discriminator; } } 
 
        /// 
        /// Get the discriminator value 
        /// 
        internal object DiscriminatorValue { get { return m_discriminatorValue; } }

        ///  
        /// Visitor Design Pattern
        ///  
        ///  
        /// 
        ///  
        [DebuggerNonUserCode]
        internal override void Accept(ColumnMapVisitor visitor, TArgType arg)
        {
            visitor.Visit(this, arg); 
        }
 
        ///  
        /// Visitor Design Pattern
        ///  
        /// 
        /// 
        /// 
        ///  
        [DebuggerNonUserCode]
        internal override TResultType Accept(ColumnMapVisitorWithResults visitor, TArgType arg) 
        { 
            return visitor.Visit(this, arg);
        } 

        /// 
        /// Debugging support
        ///  
        /// 
        public override string ToString() 
        { 
            string str = String.Format(CultureInfo.InvariantCulture, "M{{{0}}}", this.Element.ToString());
            return str; 
        }
    }
    #endregion
 
    #region SortKeyInfo
    ///  
    ///  Represents a sort key column. Used in CollectionColumnMap. 
    /// 
    internal class SortKeyInfo 
    {
        private SimpleColumnMap m_sortKeyColumn;
        private bool m_asc;
        private string m_collation; 

        ///  
        /// Basic constructor. 
        /// 
        /// The columnMap representing the sort column 
        /// Whether ascending sort is specified
        /// An optional collation (only for string types)
        internal SortKeyInfo(SimpleColumnMap sortKeyColumn, bool asc, string collation)
        { 
            m_sortKeyColumn = sortKeyColumn;
            m_asc = asc; 
            m_collation = collation; 
        }
 
        /// 
        /// The column map for the sorting column
        /// 
        internal ColumnMap SortKeyColumn { get { return m_sortKeyColumn; }   } 

        ///  
        /// Whehter ascending sort is specified 
        /// 
        internal bool AscendingSort { get { return m_asc; } } 

        /// 
        /// The collation, if any
        ///  
        internal string Collation { get { return m_collation; } }
    } 
    #endregion 

    #region EntityIdentity 
    /// 
    /// Abstract base class representing entity identity. Used by both
    /// EntityColumnMap and RefColumnMap.
    /// An EntityIdentity captures two pieces of information - the list of keys 
    /// that uniquely identify an entity within an entityset, and the the entityset
    /// itself. 
    ///  
    internal abstract class EntityIdentity
    { 
        private readonly SimpleColumnMap[] m_keys; // list of keys

        /// 
        /// Singleton entity identity that represents the "I Don't Know What EntitySet this is" 
        /// 
        internal static SimpleEntityIdentity NoEntityIdentity = new SimpleEntityIdentity(null, new SimpleColumnMap[0]); 
 
        /// 
        /// Simple constructor - gets a list of key columns 
        /// 
        /// 
        internal EntityIdentity(SimpleColumnMap[] keyColumns)
        { 
            Debug.Assert(keyColumns != null, "Must specify column maps for key columns");
            m_keys = keyColumns; 
        } 

        ///  
        /// Get the key columns
        /// 
        internal SimpleColumnMap[] Keys { get { return m_keys; } }
    } 

    ///  
    /// This class is a "simple" representation of the entity identity, where the 
    /// entityset containing the entity is known a priori. This may be because
    /// there is exactly one entityset for the entity; or because it is inferrable 
    /// from the query that only one entityset is relevant here
    /// 
    internal class SimpleEntityIdentity : EntityIdentity
    { 
        private md.EntitySet m_entitySet; // the entity set
 
        ///  
        /// Basic constructor.
        /// Note: the entitySet may be null - in which case, we are referring to 
        /// a transient entity
        /// 
        /// The entityset
        /// key columns of the entity 
        internal SimpleEntityIdentity(md.EntitySet entitySet, SimpleColumnMap[] keyColumns)
            : base(keyColumns) 
        { 
            // the entityset may be null
            m_entitySet = entitySet; 
        }

        /// 
        /// The entityset containing the entity 
        /// 
        internal md.EntitySet EntitySet { get { return m_entitySet; } } 
 
        /// 
        /// Debugging support 
        /// 
        /// 
        public override string ToString()
        { 
            StringBuilder sb = new StringBuilder();
            string separator = String.Empty; 
            sb.AppendFormat(CultureInfo.InvariantCulture, "[(ES={0}) (Keys={", this.EntitySet.Name); 
            foreach (SimpleColumnMap c in this.Keys)
            { 
                sb.AppendFormat(CultureInfo.InvariantCulture, "{0}{1}", separator, c);
                separator = ",";
            }
            sb.AppendFormat(CultureInfo.InvariantCulture, "})]"); 
            return sb.ToString();
        } 
    } 

    ///  
    /// This class also represents entity identity. However, this class addresses
    /// those scenarios where the entityset for the entity is not uniquely known
    /// a priori. Instead, the query is annotated with information, and based on
    /// the resulting information, the appropriate entityset is identified. 
    /// Specifically, the specific entityset is represented as a SimpleColumnMap
    /// in the query. The value of that column is used to look up a dictionary, 
    /// and then identify the appropriate entity set. 
    /// It is entirely possible that no entityset may be located for the entity
    /// instance - this represents a transient entity instance 
    /// 
    internal class DiscriminatedEntityIdentity : EntityIdentity
    {
        private SimpleColumnMap m_entitySetColumn;  // (optional) column map representing the entity set 
        private md.EntitySet[] m_entitySetMap; // optional dictionary that maps values to entitysets
 
        ///  
        /// Simple constructor
        ///  
        /// column map representing the entityset
        /// Map from value -> the appropriate entityset
        /// list of key columns
        internal DiscriminatedEntityIdentity(SimpleColumnMap entitySetColumn, md.EntitySet[] entitySetMap, 
            SimpleColumnMap[] keyColumns)
            : base(keyColumns) 
        { 
            Debug.Assert(entitySetColumn != null, "Must specify a column map to identify the entity set");
            Debug.Assert(entitySetMap != null, "Must specify a dictionary to look up entitysets"); 
            m_entitySetColumn = entitySetColumn;
            m_entitySetMap = entitySetMap;
        }
 
        /// 
        /// Get the column map representing the entityset 
        ///  
        internal SimpleColumnMap EntitySetColumnMap { get { return m_entitySetColumn; } }
 
        /// 
        /// Return the entityset map
        /// 
        internal md.EntitySet[] EntitySetMap 
        {
            get { return m_entitySetMap; } 
        } 

        ///  
        /// Debugging support
        /// 
        /// 
        public override string ToString() 
        {
            StringBuilder sb = new StringBuilder(); 
            string separator = String.Empty; 
            sb.AppendFormat(CultureInfo.InvariantCulture, "[(Keys={");
            foreach (SimpleColumnMap c in this.Keys) 
            {
                sb.AppendFormat(CultureInfo.InvariantCulture, "{0}{1}", separator, c);
                separator = ",";
            } 
            sb.AppendFormat(CultureInfo.InvariantCulture, "})]");
            return sb.ToString(); 
        } 
    }
    #endregion 

    #region internal classes

    ///  
    /// A VarRefColumnMap is our intermediate representation of a ColumnMap.
    /// Eventually, this gets translated into a regular ColumnMap - during the CodeGen phase 
    ///  
    internal class VarRefColumnMap : SimpleColumnMap
    { 
        #region Public Methods
        /// 
        /// Get the Var that produces this column's value
        ///  
        internal InternalTrees.Var Var
        { 
            get { return m_var; } 
        }
        #endregion 

        #region Constructors
        /// 
        /// Simple constructor 
        /// 
        /// datatype of this Var 
        /// the name of the column 
        /// the var producing the value for this column
        internal VarRefColumnMap(md.TypeUsage type, string name, InternalTrees.Var v) 
            : base(type, name)
        {
            m_var = v;
        } 

        internal VarRefColumnMap(InternalTrees.Var v) 
            : this(v.Type, null, v) 
        {
        } 

        /// 
        /// Visitor Design Pattern
        ///  
        /// 
        ///  
        ///  
        [DebuggerNonUserCode]
        internal override void Accept(ColumnMapVisitor visitor, TArgType arg) 
        {
            visitor.Visit(this, arg);
        }
 
        /// 
        /// Visitor Design Pattern 
        ///  
        /// 
        ///  
        /// 
        /// 
        [DebuggerNonUserCode]
        internal override TResultType Accept(ColumnMapVisitorWithResults visitor, TArgType arg) 
        {
            return visitor.Visit(this, arg); 
        } 

        ///  
        /// Debugging support
        /// 
        /// 
        public override string ToString() 
        {
            return this.IsNamed ? this.Name : String.Format(CultureInfo.InvariantCulture, "{0}", m_var.Id); 
        } 
        #endregion
 
        #region private state
        private InternalTrees.Var m_var;
        #endregion
    } 
    #endregion
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner  [....], [....]
//--------------------------------------------------------------------- 
 
using System;
using System.Text; 
using System.Collections.Generic;
using md = System.Data.Metadata.Edm;
using mp = System.Data.Mapping;
using System.Globalization; 
using System.Diagnostics;
using System.Data.Common.Utils; 
 
// A ColumnMap is a data structure that maps columns from the C space to
// the corresponding columns from one or more underlying readers. 
//
// ColumnMaps are used by the ResultAssembly phase to assemble results in the
// desired shape (as requested by the caller) from a set of underlying
// (usually) flat readers. ColumnMaps are produced as part of the PlanCompiler 
// module of the bridge, and are consumed by the Execution phase of the bridge.
// 
// * Simple (scalar) columns (and UDTs) are represented by a SimpleColumnMap 
// * Record type columns are represented by a RecordColumnMap
// * A nominal type instance (that supports inheritance) is usually represented 
//     by a PolymorphicColumnMap - this polymorphicColumnMap contains information
//     about the type discriminator (assumed to be a simple column), and a mapping
//     from type-discriminator value to the column map for the specific type
// * The specific type for nominal types is represented by ComplexTypeColumnMap 
//     for complextype columns, and EntityColumnMap for entity type columns.
//     EntityColumnMaps additionally have an EntityIdentity that describes 
//     the entity identity. The entity identity is logically just a set of keys 
//     (and the column maps), plus a column map that helps to identify the
//     the appropriate entity set for the entity instance 
// * Refs are represented by a RefColumnMap. The RefColumnMap simply contains an
//   EntityIdentity
// * Collections are represented by either a SimpleCollectionColumnMap or a
//     DiscriminatedCollectionColumnMap. Both of these contain a column map for the 
//     element type, and an optional list of simple columns (the keys) that help
//     demarcate the elements of a specific collection instance. 
//     The DiscriminatedCollectionColumnMap is used in scenarios when the containing 
//     row has multiple collections, and the different collection properties must be
//     differentiated. This differentiation is achieved via a Discriminator column 
//     (a simple column), and a Discriminator value. The value of the Discriminator
//     column is read and compared with the DiscriminatorValue stored in this map
//     to determine if we're dealing with the current collection.
// 
// NOTE:
//  * Key columns are assumed to be SimpleColumns. There may be more than one key 
//      column (applies to EntityColumnMap and *CollectionColumnMap) 
//  * TypeDiscriminator and Discriminator columns are also considered to be
//      SimpleColumns. There are singleton columns. 
//
// It is the responsibility of the PlanCompiler phase to produce the right column
// maps.
// 
// The result of a query is always assumed to be a collection. The ColumnMap that we
// return as part of plan compilation refers to the element type of this collection 
// - the element type is usually a structured type, but may also be a simple type 
//   or another collection type. How does the DbRecord framework handle these cases?
// 
//
namespace System.Data.Query.InternalTrees
{
    ///  
    /// Represents a column
    ///  
    internal abstract class ColumnMap 
    {
        private md.TypeUsage m_type; // column datatype 
        private string m_name; // name of the column

        /// 
        /// Default Column Name; should not be set until CodeGen once we're done 
        /// with all our transformations that might give us a good name, but put
        /// here for ease of finding it. 
        ///  
        internal const string DefaultColumnName = "Value";
 
        /// 
        /// Simple constructor - just needs the name and type of the column
        /// 
        /// column type 
        /// column name
        internal ColumnMap(md.TypeUsage type, string name) 
        { 
            Debug.Assert(type != null, "Unspecified type");
            m_type = type; 
            m_name = name;
        }

        ///  
        /// Get the column's datatype
        ///  
        internal md.TypeUsage Type { get { return m_type; } } 

        ///  
        /// Get the column name
        /// 
        internal string Name
        { 
            get { return m_name; }
            set 
            { 
                Debug.Assert(!String.IsNullOrEmpty(value), "invalid name?");
                m_name = value; 
            }
        }

        ///  
        /// Returns whether the column already has a name;
        ///  
        internal bool IsNamed 
        {
            get { return m_name != null; } 
        }

        /// 
        /// Visitor Design Pattern 
        /// 
        ///  
        ///  
        /// 
        ///  
        [DebuggerNonUserCode]
        internal abstract void Accept(ColumnMapVisitor visitor, TArgType arg);

        ///  
        /// Visitor Design Pattern
        ///  
        ///  
        /// 
        ///  
        /// 
        /// 
        [DebuggerNonUserCode]
        internal abstract TResultType Accept(ColumnMapVisitorWithResults visitor, TArgType arg); 
    }
 
    ///  
    /// Base class for simple column maps; can be either a VarRefColumnMap or
    /// ScalarColumnMap; the former is used pretty much throughout the PlanCompiler, 
    /// while the latter will only be used once we generate the final Plan.
    /// 
    internal abstract class SimpleColumnMap : ColumnMap
    { 
        /// 
        /// Basic constructor 
        ///  
        /// datatype for this column
        /// column name 
        internal SimpleColumnMap(md.TypeUsage type, string name)
            : base(type, name)
        {
        } 
    }
 
    ///  
    /// Column map for a scalar column - maps 1-1 with a column from a
    /// row of the underlying reader 
    /// 
    internal class ScalarColumnMap : SimpleColumnMap
    {
        private int m_commandId; 
        private int m_columnPos;
 
        ///  
        /// Basic constructor
        ///  
        /// datatype for this column
        /// column name
        /// Underlying command to locate this column
        /// Position in underlying reader 
        internal ScalarColumnMap(md.TypeUsage type, string name, int commandId, int columnPos)
            : base(type, name) 
        { 
            Debug.Assert(commandId >= 0, "invalid command id");
            Debug.Assert(columnPos >= 0, "invalid column position"); 
            m_commandId = commandId;
            m_columnPos = columnPos;
        }
 
        /// 
        /// The command (reader, really) to get this column value from 
        ///  
        internal int CommandId { get { return m_commandId; } }
        ///  
        /// Column position within the reader of the command
        /// 
        internal int ColumnPos { get { return m_columnPos; } }
 
        /// 
        /// Visitor Design Pattern 
        ///  
        /// 
        ///  
        /// 
        [DebuggerNonUserCode]
        internal override void Accept(ColumnMapVisitor visitor, TArgType arg)
        { 
            visitor.Visit(this, arg);
        } 
 
        /// 
        /// Visitor Design Pattern 
        /// 
        /// 
        /// 
        ///  
        /// 
        [DebuggerNonUserCode] 
        internal override TResultType Accept(ColumnMapVisitorWithResults visitor, TArgType arg) 
        {
            return visitor.Visit(this, arg); 
        }

        /// 
        /// Debugging support 
        /// 
        ///  
        public override string ToString() 
        {
            return String.Format(CultureInfo.InvariantCulture, "S({0},{1})", this.CommandId, this.ColumnPos); 
        }
    }

    #region Structured Columns 
    /// 
    /// Represents a column map for a structured column 
    ///  
    internal abstract class StructuredColumnMap : ColumnMap
    { 
        private readonly ColumnMap[] m_properties;

        /// 
        /// Structured columnmap constructor 
        /// 
        /// datatype for this column 
        /// column name 
        /// list of properties
        internal StructuredColumnMap(md.TypeUsage type, string name, ColumnMap[] properties) 
            : base(type, name)
        {
            Debug.Assert(properties != null, "No properties (gasp!) for a structured type");
            m_properties = properties; 
        }
 
        ///  
        /// Get the null sentinel column, if any.  Virtual so only derived column map
        /// types that can have NullSentinel have to provide storage, etc. 
        /// 
        virtual internal SimpleColumnMap NullSentinel { get { return null; } }

        ///  
        /// Get the list of properties that constitute this structured type
        ///  
        internal ColumnMap[] Properties { get { return m_properties; } } 

        ///  
        /// Debugging support
        /// 
        /// 
        public override string ToString() 
        {
            StringBuilder sb = new StringBuilder(); 
            string separator = String.Empty; 
            sb.Append("{");
            foreach (ColumnMap c in this.Properties) 
            {
                sb.AppendFormat(CultureInfo.InvariantCulture, "{0}{1}", separator, c);
                separator = ",";
            } 
            sb.Append("}");
            return sb.ToString(); 
        } 
    }
 
    /// 
    /// Represents a record (an untyped structured column)
    /// 
    internal class RecordColumnMap : StructuredColumnMap 
    {
        private SimpleColumnMap m_nullSentinel; 
 
        /// 
        /// Constructor for a record column map 
        /// 
        /// Datatype of this column
        /// column name
        /// List of ColumnMaps - one for each property 
        internal RecordColumnMap(md.TypeUsage type, string name, ColumnMap[] properties, SimpleColumnMap nullSentinel)
            : base(type, name, properties) 
        { 
            m_nullSentinel = nullSentinel;
        } 

        /// 
        /// Get the type Nullability column
        ///  
        internal override SimpleColumnMap NullSentinel { get { return m_nullSentinel; } }
 
        ///  
        /// Visitor Design Pattern
        ///  
        /// 
        /// 
        /// 
        [DebuggerNonUserCode] 
        internal override void Accept(ColumnMapVisitor visitor, TArgType arg)
        { 
            visitor.Visit(this, arg); 
        }
 
        /// 
        /// Visitor Design Pattern
        /// 
        ///  
        /// 
        ///  
        ///  
        [DebuggerNonUserCode]
        internal override TResultType Accept(ColumnMapVisitorWithResults visitor, TArgType arg) 
        {
            return visitor.Visit(this, arg);
        }
    } 

    ///  
    /// Column map for a "typed" column 
    /// - either an entity type or a complex type
    ///  
    internal abstract class TypedColumnMap : StructuredColumnMap
    {
        /// 
        /// Typed columnMap constructor 
        /// 
        /// Datatype of column 
        /// column name 
        /// List of column maps - one for each property
        internal TypedColumnMap(md.TypeUsage type, string name, ColumnMap[] properties) 
            : base(type, name, properties) { }
    }

    ///  
    /// Represents a polymorphic typed column - either an entity or
    /// a complex type. 
    ///  
    internal class SimplePolymorphicColumnMap : TypedColumnMap
    { 
        private SimpleColumnMap m_typeDiscriminator;
        private Dictionary m_typedColumnMap;

        ///  
        /// Internal constructor
        ///  
        /// datatype of the column 
        /// column name
        /// column map for type discriminator column 
        /// base list of fields common to all types
        /// map from type discriminator value->columnMap
        internal SimplePolymorphicColumnMap(md.TypeUsage type,
            string name, 
            ColumnMap[] baseTypeColumns,
            SimpleColumnMap typeDiscriminator, 
            Dictionary typeChoices) 
            : base(type, name, baseTypeColumns)
        { 
            Debug.Assert(typeDiscriminator != null, "Must specify a type discriminator column");
            Debug.Assert(typeChoices != null, "No type choices for polymorphic column");
            m_typedColumnMap = typeChoices;
            m_typeDiscriminator = typeDiscriminator; 
        }
 
        ///  
        /// Get the type discriminator column
        ///  
        internal SimpleColumnMap TypeDiscriminator { get { return m_typeDiscriminator; } }

        /// 
        /// Get the type mapping 
        /// 
        internal Dictionary TypeChoices 
        { 
            get { return m_typedColumnMap; }
        } 

        /// 
        /// Visitor Design Pattern
        ///  
        /// 
        ///  
        ///  
        [DebuggerNonUserCode]
        internal override void Accept(ColumnMapVisitor visitor, TArgType arg) 
        {
            visitor.Visit(this, arg);
        }
 
        /// 
        /// Visitor Design Pattern 
        ///  
        /// 
        ///  
        /// 
        /// 
        [DebuggerNonUserCode]
        internal override TResultType Accept(ColumnMapVisitorWithResults visitor, TArgType arg) 
        {
            return visitor.Visit(this, arg); 
        } 

        ///  
        /// Debugging support
        /// 
        /// 
        public override string ToString() 
        {
            StringBuilder sb = new StringBuilder(); 
            string separator = String.Empty; 

            sb.AppendFormat(CultureInfo.InvariantCulture, "P{{TypeId={0}, ", this.TypeDiscriminator); 
            foreach (KeyValuePair kv in this.TypeChoices)
            {
                sb.AppendFormat(CultureInfo.InvariantCulture, "{0}({1},{2})", separator, kv.Key, kv.Value);
                separator = ","; 
            }
            sb.Append("}"); 
            return sb.ToString(); 
        }
    } 

    /// 
    /// Represents a function import column map.
    ///  
    internal class MultipleDiscriminatorPolymorphicColumnMap : TypedColumnMap
    { 
        private readonly SimpleColumnMap[] m_typeDiscriminators; 
        private readonly Dictionary m_typeChoices;
        private readonly Func m_discriminate; 

        /// 
        /// Internal constructor
        ///  
        internal MultipleDiscriminatorPolymorphicColumnMap(md.TypeUsage type,
            string name, 
            ColumnMap[] baseTypeColumns, 
            SimpleColumnMap[] typeDiscriminators,
            Dictionary typeChoices, 
            Func discriminate)
            : base(type, name, baseTypeColumns)
        {
            Debug.Assert(typeDiscriminators != null, "Must specify type discriminator columns"); 
            Debug.Assert(typeChoices != null, "No type choices for polymorphic column");
            Debug.Assert(discriminate != null, "Must specify discriminate"); 
 
            m_typeDiscriminators = typeDiscriminators;
            m_typeChoices = typeChoices; 
            m_discriminate = discriminate;
        }

        ///  
        /// Get the type discriminator column
        ///  
        internal SimpleColumnMap[] TypeDiscriminators { get { return m_typeDiscriminators; } } 

        ///  
        /// Get the type mapping
        /// 
        internal Dictionary TypeChoices
        { 
            get { return m_typeChoices; }
        } 
 
        /// 
        /// Gets discriminator delegate 
        /// 
        internal Func Discriminate
        {
            get { return m_discriminate; } 
        }
 
        ///  
        /// Visitor Design Pattern
        ///  
        [DebuggerNonUserCode]
        internal override void Accept(ColumnMapVisitor visitor, TArgType arg)
        {
            visitor.Visit(this, arg); 
        }
 
        ///  
        /// Visitor Design Pattern
        ///  
        [DebuggerNonUserCode]
        internal override TResultType Accept(ColumnMapVisitorWithResults visitor, TArgType arg)
        {
            return visitor.Visit(this, arg); 
        }
 
        ///  
        /// Debugging support
        ///  
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            string separator = String.Empty; 

            sb.AppendFormat(CultureInfo.InvariantCulture, "P{{TypeId=<{0}>, ", StringUtil.ToCommaSeparatedString(this.TypeDiscriminators)); 
            foreach (var kv in this.TypeChoices) 
            {
                sb.AppendFormat(CultureInfo.InvariantCulture, "{0}(<{1}>,{2})", separator, kv.Key, kv.Value); 
                separator = ",";
            }
            sb.Append("}");
            return sb.ToString(); 
        }
    } 
 
    /// 
    /// Represents a column map for a specific complextype 
    /// 
    internal class ComplexTypeColumnMap : TypedColumnMap
    {
        private SimpleColumnMap m_nullSentinel; 

        ///  
        /// Constructor 
        /// 
        /// column Datatype 
        /// column name
        /// list of properties
        internal ComplexTypeColumnMap(md.TypeUsage type, string name, ColumnMap[] properties, SimpleColumnMap nullSentinel)
            : base(type, name, properties) 
        {
            m_nullSentinel = nullSentinel; 
        } 

        ///  
        /// Get the type Nullability column
        /// 
        internal override SimpleColumnMap NullSentinel { get { return m_nullSentinel; } }
 
        /// 
        /// Visitor Design Pattern 
        ///  
        /// 
        ///  
        /// 
        [DebuggerNonUserCode]
        internal override void Accept(ColumnMapVisitor visitor, TArgType arg)
        { 
            visitor.Visit(this, arg);
        } 
 
        /// 
        /// Visitor Design Pattern 
        /// 
        /// 
        /// 
        ///  
        /// 
        [DebuggerNonUserCode] 
        internal override TResultType Accept(ColumnMapVisitorWithResults visitor, TArgType arg) 
        {
            return visitor.Visit(this, arg); 
        }

        /// 
        /// Debugging support 
        /// 
        ///  
        public override string ToString() 
        {
            string str = String.Format(CultureInfo.InvariantCulture, "C{0}", base.ToString()); 
            return str;
        }

    } 

    ///  
    /// Represents a column map for a specific entity type 
    /// 
    internal class EntityColumnMap : TypedColumnMap 
    {
        private EntityIdentity m_entityIdentity;

        ///  
        /// constructor
        ///  
        /// column datatype 
        /// column name
        /// entity identity information 
        /// list of properties
        internal EntityColumnMap(md.TypeUsage type, string name, ColumnMap[] properties, EntityIdentity entityIdentity)
            : base(type, name, properties)
        { 
            Debug.Assert(entityIdentity != null, "Must specify an entity identity");
            m_entityIdentity = entityIdentity; 
        } 

        ///  
        /// Get the entity identity information
        /// 
        internal EntityIdentity EntityIdentity { get { return m_entityIdentity; } }
 
        /// 
        /// Visitor Design Pattern 
        ///  
        /// 
        ///  
        /// 
        [DebuggerNonUserCode]
        internal override void Accept(ColumnMapVisitor visitor, TArgType arg)
        { 
            visitor.Visit(this, arg);
        } 
 
        /// 
        /// Visitor Design Pattern 
        /// 
        /// 
        /// 
        ///  
        /// 
        [DebuggerNonUserCode] 
        internal override TResultType Accept(ColumnMapVisitorWithResults visitor, TArgType arg) 
        {
            return visitor.Visit(this, arg); 
        }

        /// 
        /// Debugging support 
        /// 
        ///  
        public override string ToString() 
        {
            string str = String.Format(CultureInfo.InvariantCulture, "E{0}", base.ToString()); 
            return str;
        }
    }
 
    /// 
    /// A column map that represents a ref column. 
    ///  
    internal class RefColumnMap: ColumnMap
    { 
        private EntityIdentity m_entityIdentity;

        /// 
        /// Constructor for a ref column 
        /// 
        /// column datatype 
        /// column name 
        /// identity information for this entity
        internal RefColumnMap(md.TypeUsage type, string name, 
            EntityIdentity entityIdentity)
            : base(type, name)
        {
            Debug.Assert(entityIdentity != null, "Must specify entity identity information"); 
            m_entityIdentity = entityIdentity;
        } 
 
        /// 
        /// Get the entity identity information for this ref 
        /// 
        internal EntityIdentity EntityIdentity { get { return m_entityIdentity; } }

        ///  
        /// Visitor Design Pattern
        ///  
        ///  
        /// 
        ///  
        [DebuggerNonUserCode]
        internal override void Accept(ColumnMapVisitor visitor, TArgType arg)
        {
            visitor.Visit(this, arg); 
        }
 
        ///  
        /// Visitor Design Pattern
        ///  
        /// 
        /// 
        /// 
        ///  
        [DebuggerNonUserCode]
        internal override TResultType Accept(ColumnMapVisitorWithResults visitor, TArgType arg) 
        { 
            return visitor.Visit(this, arg);
        } 
    }
    #endregion

    #region Collections 
    /// 
    /// Represents a column map for a collection column. 
    /// The "element" represents the element of the collection - usually a Structured 
    /// type, but occasionally a collection/simple type as well.
    /// The "ForeignKeys" property is optional (but usually necessary) to determine the 
    /// elements of the collection.
    /// 
    internal abstract class CollectionColumnMap : ColumnMap
    { 
        private readonly ColumnMap m_element;
        private readonly SimpleColumnMap[] m_foreignKeys; 
        private readonly SimpleColumnMap[] m_keys; 
        private readonly SortKeyInfo[] m_sortKeys;
 
        /// 
        /// Constructor
        /// 
        /// datatype of column 
        /// column name
        /// column map for collection element 
        /// List of keys 
        /// List of foreign keys
        /// List of sort keys 
        internal CollectionColumnMap(md.TypeUsage type, string name, ColumnMap elementMap, SimpleColumnMap[] keys, SimpleColumnMap[] foreignKeys, SortKeyInfo[] sortKeys)
            : base(type, name)
        {
            Debug.Assert(elementMap != null, "Must specify column map for element"); 

            m_element = elementMap; 
            m_keys = keys ?? new SimpleColumnMap[0]; 
            m_foreignKeys = foreignKeys ?? new SimpleColumnMap[0];
            m_sortKeys = sortKeys ?? new SortKeyInfo[0]; 
        }

        /// 
        /// Get the list of columns that may comprise the foreign key 
        /// 
        internal SimpleColumnMap[] ForeignKeys 
        { 
            get { return m_foreignKeys; }
        } 

        /// 
        /// Get the list of columns that may comprise the key
        ///  
        internal SimpleColumnMap[] Keys
        { 
            get { return m_keys; } 
        }
 
        /// 
        /// Get the list of sort columns
        /// 
        internal SortKeyInfo[] SortKeys 
        {
            get { return m_sortKeys; } 
        } 

        ///  
        /// Get the column map describing the collection element
        /// 
        internal ColumnMap Element
        { 
            get { return m_element; }
        } 
    } 

    ///  
    /// Represents a "simple" collection map.
    /// 
    internal class SimpleCollectionColumnMap : CollectionColumnMap
    { 
        /// 
        /// Basic constructor 
        ///  
        /// Column datatype
        /// column name 
        /// column map for the element of the collection
        /// list of key columns
        /// list of foreign key columns
        /// list of sort key columns 
        internal SimpleCollectionColumnMap(md.TypeUsage type, string name,
            ColumnMap elementMap, 
            SimpleColumnMap[] keys, 
            SimpleColumnMap[] foreignKeys,
            SortKeyInfo[] sortKeys) 
            : base(type, name, elementMap, keys, foreignKeys, sortKeys) { }

        /// 
        /// Visitor Design Pattern 
        /// 
        ///  
        ///  
        /// 
        [DebuggerNonUserCode] 
        internal override void Accept(ColumnMapVisitor visitor, TArgType arg)
        {
            visitor.Visit(this, arg);
        } 

        ///  
        /// Visitor Design Pattern 
        /// 
        ///  
        /// 
        /// 
        /// 
        [DebuggerNonUserCode] 
        internal override TResultType Accept(ColumnMapVisitorWithResults visitor, TArgType arg)
        { 
            return visitor.Visit(this, arg); 
        }
    } 

    /// 
    /// Represents a "discriminated" collection column.
    /// This represents a scenario when multiple collections are represented 
    /// at the same level of the container row, and there is a need to distinguish
    /// between these collections 
    ///  
    internal class DiscriminatedCollectionColumnMap : CollectionColumnMap
    { 
        private SimpleColumnMap m_discriminator;
        private object m_discriminatorValue;

        ///  
        /// Internal constructor
        ///  
        /// Column datatype 
        /// column name
        /// column map for collection element 
        /// Keys for the collection
        /// Foreign keys for the collection
        /// Sort keys for the collection
        /// Discriminator column map 
        /// Discriminator value
        internal DiscriminatedCollectionColumnMap(md.TypeUsage type, string name, 
            ColumnMap elementMap, 
            SimpleColumnMap[] keys,
            SimpleColumnMap[] foreignKeys, 
            SortKeyInfo[] sortKeys,
            SimpleColumnMap discriminator,
            object discriminatorValue)
            : base(type, name, elementMap, keys, foreignKeys, sortKeys) 
        {
            Debug.Assert(discriminator != null, "Must specify a column map for the collection discriminator"); 
            Debug.Assert(discriminatorValue != null, "Must specify a discriminator value"); 
            m_discriminator = discriminator;
            m_discriminatorValue = discriminatorValue; 
        }

        /// 
        /// Get the column that describes the discriminator 
        /// 
        internal SimpleColumnMap Discriminator { get { return m_discriminator; } } 
 
        /// 
        /// Get the discriminator value 
        /// 
        internal object DiscriminatorValue { get { return m_discriminatorValue; } }

        ///  
        /// Visitor Design Pattern
        ///  
        ///  
        /// 
        ///  
        [DebuggerNonUserCode]
        internal override void Accept(ColumnMapVisitor visitor, TArgType arg)
        {
            visitor.Visit(this, arg); 
        }
 
        ///  
        /// Visitor Design Pattern
        ///  
        /// 
        /// 
        /// 
        ///  
        [DebuggerNonUserCode]
        internal override TResultType Accept(ColumnMapVisitorWithResults visitor, TArgType arg) 
        { 
            return visitor.Visit(this, arg);
        } 

        /// 
        /// Debugging support
        ///  
        /// 
        public override string ToString() 
        { 
            string str = String.Format(CultureInfo.InvariantCulture, "M{{{0}}}", this.Element.ToString());
            return str; 
        }
    }
    #endregion
 
    #region SortKeyInfo
    ///  
    ///  Represents a sort key column. Used in CollectionColumnMap. 
    /// 
    internal class SortKeyInfo 
    {
        private SimpleColumnMap m_sortKeyColumn;
        private bool m_asc;
        private string m_collation; 

        ///  
        /// Basic constructor. 
        /// 
        /// The columnMap representing the sort column 
        /// Whether ascending sort is specified
        /// An optional collation (only for string types)
        internal SortKeyInfo(SimpleColumnMap sortKeyColumn, bool asc, string collation)
        { 
            m_sortKeyColumn = sortKeyColumn;
            m_asc = asc; 
            m_collation = collation; 
        }
 
        /// 
        /// The column map for the sorting column
        /// 
        internal ColumnMap SortKeyColumn { get { return m_sortKeyColumn; }   } 

        ///  
        /// Whehter ascending sort is specified 
        /// 
        internal bool AscendingSort { get { return m_asc; } } 

        /// 
        /// The collation, if any
        ///  
        internal string Collation { get { return m_collation; } }
    } 
    #endregion 

    #region EntityIdentity 
    /// 
    /// Abstract base class representing entity identity. Used by both
    /// EntityColumnMap and RefColumnMap.
    /// An EntityIdentity captures two pieces of information - the list of keys 
    /// that uniquely identify an entity within an entityset, and the the entityset
    /// itself. 
    ///  
    internal abstract class EntityIdentity
    { 
        private readonly SimpleColumnMap[] m_keys; // list of keys

        /// 
        /// Singleton entity identity that represents the "I Don't Know What EntitySet this is" 
        /// 
        internal static SimpleEntityIdentity NoEntityIdentity = new SimpleEntityIdentity(null, new SimpleColumnMap[0]); 
 
        /// 
        /// Simple constructor - gets a list of key columns 
        /// 
        /// 
        internal EntityIdentity(SimpleColumnMap[] keyColumns)
        { 
            Debug.Assert(keyColumns != null, "Must specify column maps for key columns");
            m_keys = keyColumns; 
        } 

        ///  
        /// Get the key columns
        /// 
        internal SimpleColumnMap[] Keys { get { return m_keys; } }
    } 

    ///  
    /// This class is a "simple" representation of the entity identity, where the 
    /// entityset containing the entity is known a priori. This may be because
    /// there is exactly one entityset for the entity; or because it is inferrable 
    /// from the query that only one entityset is relevant here
    /// 
    internal class SimpleEntityIdentity : EntityIdentity
    { 
        private md.EntitySet m_entitySet; // the entity set
 
        ///  
        /// Basic constructor.
        /// Note: the entitySet may be null - in which case, we are referring to 
        /// a transient entity
        /// 
        /// The entityset
        /// key columns of the entity 
        internal SimpleEntityIdentity(md.EntitySet entitySet, SimpleColumnMap[] keyColumns)
            : base(keyColumns) 
        { 
            // the entityset may be null
            m_entitySet = entitySet; 
        }

        /// 
        /// The entityset containing the entity 
        /// 
        internal md.EntitySet EntitySet { get { return m_entitySet; } } 
 
        /// 
        /// Debugging support 
        /// 
        /// 
        public override string ToString()
        { 
            StringBuilder sb = new StringBuilder();
            string separator = String.Empty; 
            sb.AppendFormat(CultureInfo.InvariantCulture, "[(ES={0}) (Keys={", this.EntitySet.Name); 
            foreach (SimpleColumnMap c in this.Keys)
            { 
                sb.AppendFormat(CultureInfo.InvariantCulture, "{0}{1}", separator, c);
                separator = ",";
            }
            sb.AppendFormat(CultureInfo.InvariantCulture, "})]"); 
            return sb.ToString();
        } 
    } 

    ///  
    /// This class also represents entity identity. However, this class addresses
    /// those scenarios where the entityset for the entity is not uniquely known
    /// a priori. Instead, the query is annotated with information, and based on
    /// the resulting information, the appropriate entityset is identified. 
    /// Specifically, the specific entityset is represented as a SimpleColumnMap
    /// in the query. The value of that column is used to look up a dictionary, 
    /// and then identify the appropriate entity set. 
    /// It is entirely possible that no entityset may be located for the entity
    /// instance - this represents a transient entity instance 
    /// 
    internal class DiscriminatedEntityIdentity : EntityIdentity
    {
        private SimpleColumnMap m_entitySetColumn;  // (optional) column map representing the entity set 
        private md.EntitySet[] m_entitySetMap; // optional dictionary that maps values to entitysets
 
        ///  
        /// Simple constructor
        ///  
        /// column map representing the entityset
        /// Map from value -> the appropriate entityset
        /// list of key columns
        internal DiscriminatedEntityIdentity(SimpleColumnMap entitySetColumn, md.EntitySet[] entitySetMap, 
            SimpleColumnMap[] keyColumns)
            : base(keyColumns) 
        { 
            Debug.Assert(entitySetColumn != null, "Must specify a column map to identify the entity set");
            Debug.Assert(entitySetMap != null, "Must specify a dictionary to look up entitysets"); 
            m_entitySetColumn = entitySetColumn;
            m_entitySetMap = entitySetMap;
        }
 
        /// 
        /// Get the column map representing the entityset 
        ///  
        internal SimpleColumnMap EntitySetColumnMap { get { return m_entitySetColumn; } }
 
        /// 
        /// Return the entityset map
        /// 
        internal md.EntitySet[] EntitySetMap 
        {
            get { return m_entitySetMap; } 
        } 

        ///  
        /// Debugging support
        /// 
        /// 
        public override string ToString() 
        {
            StringBuilder sb = new StringBuilder(); 
            string separator = String.Empty; 
            sb.AppendFormat(CultureInfo.InvariantCulture, "[(Keys={");
            foreach (SimpleColumnMap c in this.Keys) 
            {
                sb.AppendFormat(CultureInfo.InvariantCulture, "{0}{1}", separator, c);
                separator = ",";
            } 
            sb.AppendFormat(CultureInfo.InvariantCulture, "})]");
            return sb.ToString(); 
        } 
    }
    #endregion 

    #region internal classes

    ///  
    /// A VarRefColumnMap is our intermediate representation of a ColumnMap.
    /// Eventually, this gets translated into a regular ColumnMap - during the CodeGen phase 
    ///  
    internal class VarRefColumnMap : SimpleColumnMap
    { 
        #region Public Methods
        /// 
        /// Get the Var that produces this column's value
        ///  
        internal InternalTrees.Var Var
        { 
            get { return m_var; } 
        }
        #endregion 

        #region Constructors
        /// 
        /// Simple constructor 
        /// 
        /// datatype of this Var 
        /// the name of the column 
        /// the var producing the value for this column
        internal VarRefColumnMap(md.TypeUsage type, string name, InternalTrees.Var v) 
            : base(type, name)
        {
            m_var = v;
        } 

        internal VarRefColumnMap(InternalTrees.Var v) 
            : this(v.Type, null, v) 
        {
        } 

        /// 
        /// Visitor Design Pattern
        ///  
        /// 
        ///  
        ///  
        [DebuggerNonUserCode]
        internal override void Accept(ColumnMapVisitor visitor, TArgType arg) 
        {
            visitor.Visit(this, arg);
        }
 
        /// 
        /// Visitor Design Pattern 
        ///  
        /// 
        ///  
        /// 
        /// 
        [DebuggerNonUserCode]
        internal override TResultType Accept(ColumnMapVisitorWithResults visitor, TArgType arg) 
        {
            return visitor.Visit(this, arg); 
        } 

        ///  
        /// Debugging support
        /// 
        /// 
        public override string ToString() 
        {
            return this.IsNamed ? this.Name : String.Format(CultureInfo.InvariantCulture, "{0}", m_var.Id); 
        } 
        #endregion
 
        #region private state
        private InternalTrees.Var m_var;
        #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