ColumnMap.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Query / InternalTrees / ColumnMap.cs / 1305376 / ColumnMap.cs

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

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;
 
        /// 
        /// Constructor
        /// 
        /// datatype of column 
        /// column name
        /// column map for collection element 
        /// List of keys 
        /// List of foreign keys
        internal CollectionColumnMap(md.TypeUsage type, string name, ColumnMap elementMap, SimpleColumnMap[] keys, SimpleColumnMap[] foreignKeys) 
            : 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]; 
        }
 
        /// 
        /// 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 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
        internal SimpleCollectionColumnMap(md.TypeUsage type, string name,
            ColumnMap elementMap, 
            SimpleColumnMap[] keys,
            SimpleColumnMap[] foreignKeys) 
            : base(type, name, elementMap, keys, foreignKeys) { } 

        ///  
        /// 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
        /// Discriminator column map 
        /// Discriminator value
        internal DiscriminatedCollectionColumnMap(md.TypeUsage type, string name,
            ColumnMap elementMap,
            SimpleColumnMap[] keys, 
            SimpleColumnMap[] foreignKeys,
            SimpleColumnMap discriminator, 
            object discriminatorValue) 
            : base(type, name, elementMap, keys, foreignKeys)
        { 
            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 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

        /// 
        /// 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  [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

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;
 
        /// 
        /// Constructor
        /// 
        /// datatype of column 
        /// column name
        /// column map for collection element 
        /// List of keys 
        /// List of foreign keys
        internal CollectionColumnMap(md.TypeUsage type, string name, ColumnMap elementMap, SimpleColumnMap[] keys, SimpleColumnMap[] foreignKeys) 
            : 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]; 
        }
 
        /// 
        /// 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 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
        internal SimpleCollectionColumnMap(md.TypeUsage type, string name,
            ColumnMap elementMap, 
            SimpleColumnMap[] keys,
            SimpleColumnMap[] foreignKeys) 
            : base(type, name, elementMap, keys, foreignKeys) { } 

        ///  
        /// 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
        /// Discriminator column map 
        /// Discriminator value
        internal DiscriminatedCollectionColumnMap(md.TypeUsage type, string name,
            ColumnMap elementMap,
            SimpleColumnMap[] keys, 
            SimpleColumnMap[] foreignKeys,
            SimpleColumnMap discriminator, 
            object discriminatorValue) 
            : base(type, name, elementMap, keys, foreignKeys)
        { 
            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 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

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