| 
									
										
										
										
											2016-08-03 10:59:49 +00:00
										 |  |  | //--------------------------------------------------------------------- | 
					
						
							|  |  |  | // <copyright file="StorageMappingFragment.cs" company="Microsoft"> | 
					
						
							|  |  |  | //      Copyright (c) Microsoft Corporation.  All rights reserved. | 
					
						
							|  |  |  | // </copyright> | 
					
						
							|  |  |  | // | 
					
						
							| 
									
										
										
										
											2017-08-21 15:34:15 +00:00
										 |  |  | // @owner       Microsoft | 
					
						
							|  |  |  | // @backupOwner Microsoft | 
					
						
							| 
									
										
										
										
											2016-08-03 10:59:49 +00:00
										 |  |  | //--------------------------------------------------------------------- | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using System; | 
					
						
							|  |  |  | using System.Collections.Generic; | 
					
						
							|  |  |  | using System.Linq; | 
					
						
							|  |  |  | using System.Collections.ObjectModel; | 
					
						
							|  |  |  | using System.Text; | 
					
						
							|  |  |  | using System.Data.Metadata.Edm; | 
					
						
							|  |  |  | using System.Diagnostics; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace System.Data.Mapping { | 
					
						
							|  |  |  |     /// <summary> | 
					
						
							|  |  |  |     /// Represents the metadata for mapping fragment. | 
					
						
							|  |  |  |     /// A set of mapping fragments makes up the Set mappings( EntitySet, AssociationSet or CompositionSet ) | 
					
						
							|  |  |  |     /// Each MappingFragment provides mapping for those properties of a type that map to a single table. | 
					
						
							|  |  |  |     /// </summary> | 
					
						
							|  |  |  |     /// <example> | 
					
						
							|  |  |  |     /// For Example if conceptually you could represent the CS MSL file as following | 
					
						
							|  |  |  |     /// --Mapping | 
					
						
							|  |  |  |     ///   --EntityContainerMapping ( CNorthwind-->SNorthwind ) | 
					
						
							|  |  |  |     ///     --EntitySetMapping | 
					
						
							|  |  |  |     ///       --EntityTypeMapping | 
					
						
							|  |  |  |     ///         --MappingFragment | 
					
						
							|  |  |  |     ///           --EntityKey | 
					
						
							|  |  |  |     ///             --ScalarPropertyMap ( CMemberMetadata-->SMemberMetadata ) | 
					
						
							|  |  |  |     ///           --ScalarPropertyMap ( CMemberMetadata-->SMemberMetadata ) | 
					
						
							|  |  |  |     ///       --EntityTypeMapping | 
					
						
							|  |  |  |     ///         --MappingFragment | 
					
						
							|  |  |  |     ///           --EntityKey | 
					
						
							|  |  |  |     ///             --ScalarPropertyMap ( CMemberMetadata-->SMemberMetadata ) | 
					
						
							|  |  |  |     ///           --ComplexPropertyMap | 
					
						
							|  |  |  |     ///             --ComplexTypeMapping | 
					
						
							|  |  |  |     ///               --ScalarPropertyMap ( CMemberMetadata-->SMemberMetadata ) | 
					
						
							|  |  |  |     ///               --ScalarProperyMap ( CMemberMetadata-->SMemberMetadata ) | 
					
						
							|  |  |  |     ///               --DiscriminatorProperyMap ( constant value-->SMemberMetadata ) | 
					
						
							|  |  |  |     ///             --ComplexTypeMapping | 
					
						
							|  |  |  |     ///               --ScalarPropertyMap ( CMemberMetadata-->SMemberMetadata ) | 
					
						
							|  |  |  |     ///               --ScalarProperyMap ( CMemberMetadata-->SMemberMetadata ) | 
					
						
							|  |  |  |     ///               --DiscriminatorProperyMap ( constant value-->SMemberMetadata ) | 
					
						
							|  |  |  |     ///           --ScalarPropertyMap ( CMemberMetadata-->SMemberMetadata ) | 
					
						
							|  |  |  |     ///     --AssociationSetMapping  | 
					
						
							|  |  |  |     ///       --AssociationTypeMapping | 
					
						
							|  |  |  |     ///         --MappingFragment | 
					
						
							|  |  |  |     ///           --EndPropertyMap | 
					
						
							|  |  |  |     ///             --ScalarPropertyMap ( CMemberMetadata-->SMemberMetadata ) | 
					
						
							|  |  |  |     ///             --ScalarProperyMap ( CMemberMetadata-->SMemberMetadata ) | 
					
						
							|  |  |  |     ///           --EndPropertyMap | 
					
						
							|  |  |  |     ///             --ScalarPropertyMap ( CMemberMetadata-->SMemberMetadata ) | 
					
						
							|  |  |  |     /// This class represents the metadata for all the mapping fragment elements in the  | 
					
						
							|  |  |  |     /// above example. Users can access all the top level constructs of  | 
					
						
							|  |  |  |     /// MappingFragment element like EntityKey map, Property Maps, Discriminator | 
					
						
							|  |  |  |     /// property through this mapping fragment class. | 
					
						
							|  |  |  |     /// </example> | 
					
						
							|  |  |  |     internal class StorageMappingFragment { | 
					
						
							|  |  |  |         #region Constructors | 
					
						
							|  |  |  |         /// <summary> | 
					
						
							|  |  |  |         /// Construct a new Mapping Fragment object | 
					
						
							|  |  |  |         /// </summary> | 
					
						
							|  |  |  |         /// <param name="tableExtent"></param> | 
					
						
							|  |  |  |         /// <param name="typeMapping"></param> | 
					
						
							|  |  |  |         internal StorageMappingFragment(EntitySet tableExtent, StorageTypeMapping typeMapping, bool distinctFlag) { | 
					
						
							|  |  |  |             Debug.Assert(tableExtent != null, "Table should not be null when constructing a Mapping Fragment"); | 
					
						
							|  |  |  |             Debug.Assert(typeMapping != null, "TypeMapping should not be null when constructing a Mapping Fragment"); | 
					
						
							|  |  |  |             this.m_tableExtent = tableExtent; | 
					
						
							|  |  |  |             this.m_typeMapping = typeMapping; | 
					
						
							|  |  |  |             this.m_isSQueryDistinct = distinctFlag; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         #endregion | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         #region Fields | 
					
						
							|  |  |  |         /// <summary> | 
					
						
							|  |  |  |         /// Table extent from which the properties are mapped under this fragment. | 
					
						
							|  |  |  |         /// </summary> | 
					
						
							|  |  |  |         EntitySet m_tableExtent; | 
					
						
							|  |  |  |         /// <summary> | 
					
						
							|  |  |  |         /// Type mapping under which this mapping fragment exists. | 
					
						
							|  |  |  |         /// </summary> | 
					
						
							|  |  |  |         StorageTypeMapping m_typeMapping; | 
					
						
							|  |  |  |         /// <summary> | 
					
						
							|  |  |  |         /// Condition property mappings for this mapping fragment. | 
					
						
							|  |  |  |         /// </summary> | 
					
						
							|  |  |  |         Dictionary<EdmProperty, StoragePropertyMapping> m_conditionProperties = new Dictionary<EdmProperty, StoragePropertyMapping>(EqualityComparer<EdmProperty>.Default); | 
					
						
							|  |  |  |         /// <summary> | 
					
						
							|  |  |  |         /// All the other properties . | 
					
						
							|  |  |  |         /// </summary> | 
					
						
							|  |  |  |         List<StoragePropertyMapping> m_properties = new List<StoragePropertyMapping>(); | 
					
						
							|  |  |  |         /// <summary> | 
					
						
							|  |  |  |         /// Line Number for MappingFragment element start tag. | 
					
						
							|  |  |  |         /// </summary> | 
					
						
							|  |  |  |         int m_startLineNumber; | 
					
						
							|  |  |  |         /// <summary> | 
					
						
							|  |  |  |         /// Line position for MappingFragment element start tag. | 
					
						
							|  |  |  |         /// </summary> | 
					
						
							|  |  |  |         int m_startLinePosition; | 
					
						
							|  |  |  |         bool m_isSQueryDistinct; | 
					
						
							|  |  |  |         #endregion | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         #region Properties | 
					
						
							|  |  |  |         /// <summary> | 
					
						
							|  |  |  |         /// The table from which the properties are mapped in this fragment | 
					
						
							|  |  |  |         /// </summary> | 
					
						
							|  |  |  |         internal EntitySet TableSet { | 
					
						
							|  |  |  |             get { | 
					
						
							|  |  |  |                 return this.m_tableExtent; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         internal bool IsSQueryDistinct | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             get { return m_isSQueryDistinct; } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /// <summary> | 
					
						
							|  |  |  |         /// Returns all the property mappings defined in the complex type mapping | 
					
						
							|  |  |  |         /// including Properties and Condition Properties | 
					
						
							|  |  |  |         /// </summary> | 
					
						
							|  |  |  |         internal ReadOnlyCollection<StoragePropertyMapping> AllProperties | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             get | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 List<StoragePropertyMapping> properties = new List<StoragePropertyMapping>(); | 
					
						
							|  |  |  |                 properties.AddRange(m_properties); | 
					
						
							|  |  |  |                 properties.AddRange(m_conditionProperties.Values); | 
					
						
							|  |  |  |                 return properties.AsReadOnly(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /// <summary> | 
					
						
							|  |  |  |         /// Returns all the property mappings defined in the complex type mapping | 
					
						
							|  |  |  |         /// including Properties and Condition Properties | 
					
						
							|  |  |  |         /// </summary> | 
					
						
							|  |  |  |         internal ReadOnlyCollection<StoragePropertyMapping> Properties | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             get | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 return m_properties.AsReadOnly(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         /// <summary> | 
					
						
							|  |  |  |         /// Line Number in MSL file where the Mapping Fragment Element's Start Tag is present. | 
					
						
							|  |  |  |         /// </summary> | 
					
						
							|  |  |  |         internal int StartLineNumber { | 
					
						
							|  |  |  |             get { | 
					
						
							|  |  |  |                 return m_startLineNumber; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             set { | 
					
						
							|  |  |  |                 m_startLineNumber = value; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /// <summary> | 
					
						
							|  |  |  |         /// Line Position in MSL file where the Mapping Fragment Element's Start Tag is present. | 
					
						
							|  |  |  |         /// </summary> | 
					
						
							|  |  |  |         internal int StartLinePosition { | 
					
						
							|  |  |  |             get { | 
					
						
							|  |  |  |                 return m_startLinePosition; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             set { | 
					
						
							|  |  |  |                 m_startLinePosition = value; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /// <summary> | 
					
						
							|  |  |  |         /// File URI of the MSL file | 
					
						
							|  |  |  |         /// </summary> | 
					
						
							|  |  |  |         //This should not be stored on the Fragment. Probably it should go on schema. | 
					
						
							|  |  |  |         //But this requires some thinking before we can finally decide where it should go. | 
					
						
							|  |  |  |         internal string SourceLocation { | 
					
						
							|  |  |  |             get { | 
					
						
							|  |  |  |                 return this.m_typeMapping.SetMapping.EntityContainerMapping.SourceLocation; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }         | 
					
						
							|  |  |  |         #endregion | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         #region Methods | 
					
						
							|  |  |  |         /// <summary> | 
					
						
							|  |  |  |         /// Add a property mapping as a child of this mapping fragment | 
					
						
							|  |  |  |         /// </summary> | 
					
						
							|  |  |  |         /// <param name="prop">child property mapping to be added</param> | 
					
						
							|  |  |  |         internal void AddProperty(StoragePropertyMapping prop) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             this.m_properties.Add(prop); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /// <summary> | 
					
						
							|  |  |  |         /// Add a condition property mapping as a child of this complex property mapping | 
					
						
							|  |  |  |         /// Condition Property Mapping specifies a Condition either on the C side property or S side property. | 
					
						
							|  |  |  |         /// </summary> | 
					
						
							|  |  |  |         /// <param name="conditionPropertyMap">The mapping that needs to be added</param> | 
					
						
							|  |  |  |         internal void AddConditionProperty(StorageConditionPropertyMapping conditionPropertyMap, Action<EdmMember> duplicateMemberConditionError) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             //Same Member can not have more than one Condition with in the  | 
					
						
							|  |  |  |             //same Mapping Fragment. | 
					
						
							|  |  |  |             EdmProperty conditionMember = (conditionPropertyMap.EdmProperty != null) ? conditionPropertyMap.EdmProperty : conditionPropertyMap.ColumnProperty; | 
					
						
							|  |  |  |             Debug.Assert(conditionMember != null); | 
					
						
							|  |  |  |             if (!m_conditionProperties.ContainsKey(conditionMember)) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 m_conditionProperties.Add(conditionMember, conditionPropertyMap); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 duplicateMemberConditionError(conditionMember); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /// <summary> | 
					
						
							|  |  |  |         /// This method is primarily for debugging purposes. | 
					
						
							|  |  |  |         /// Will be removed shortly. | 
					
						
							|  |  |  |         /// </summary> | 
					
						
							|  |  |  |         /// <param name="index"></param> | 
					
						
							|  |  |  |         internal virtual void Print(int index) { | 
					
						
							|  |  |  |             StorageEntityContainerMapping.GetPrettyPrintString(ref index); | 
					
						
							|  |  |  |             StringBuilder sb = new StringBuilder(); | 
					
						
							|  |  |  |             sb.Append("MappingFragment"); | 
					
						
							|  |  |  |             sb.Append("   "); | 
					
						
							|  |  |  |             sb.Append("Table Name:"); | 
					
						
							|  |  |  |             sb.Append(this.m_tableExtent.Name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             Console.WriteLine(sb.ToString()); | 
					
						
							|  |  |  |             foreach (StorageConditionPropertyMapping conditionMap in m_conditionProperties.Values) | 
					
						
							|  |  |  |                 (conditionMap).Print(index + 5); | 
					
						
							|  |  |  |             foreach (StoragePropertyMapping propertyMapping in m_properties) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 propertyMapping.Print(index + 5); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         #endregion | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |