Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / ndp / fx / src / DataEntity / System / Data / Mapping / DefaultObjectMappingItemCollection.cs / 2 / DefaultObjectMappingItemCollection.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System; using System.Diagnostics; using System.Collections; using System.Collections.Generic; using System.Xml.XPath; using System.Xml; using System.Xml.Schema; using System.Data.Metadata.Edm; using System.Data.Entity; namespace System.Data.Mapping { ////// The class creates a default OCMapping between a TypeMetadata in O space /// and an TypeMetadata in Edm space. The loader expects that for each member in /// C space type there exists a member in O space type that has the same name. The member maps will be stored in /// C space member order. /// internal class DefaultObjectMappingItemCollection : MappingItemCollection { #region Constructors ////// Constrcutor to create an instance of DefaultObjectMappingItemCollection. /// To start with we will create a Schema under which maps will be created. /// /// /// public DefaultObjectMappingItemCollection(EdmItemCollection edmCollection, ObjectItemCollection objectCollection) : base(DataSpace.OCSpace) { EntityUtil.CheckArgumentNull(edmCollection, "edmCollection"); EntityUtil.CheckArgumentNull(objectCollection, "objectCollection"); this.m_edmCollection = edmCollection; this.m_objectCollection = objectCollection; LoadPrimitiveMaps(); } #endregion #region Fields private ObjectItemCollection m_objectCollection; private EdmItemCollection m_edmCollection; private DictionaryclrTypeIndexes = new Dictionary (StringComparer.Ordinal); //Indexes into the type mappings collection based on clr type name private Dictionary cdmTypeIndexes = new Dictionary (StringComparer.Ordinal); //Indexes into the type mappings collection based on clr type name #endregion #region Methods /// /// Search for a Mapping metadata with the specified type key. /// /// identity of the type /// The dataspace that the type for which map needs to be returned belongs to /// true for case-insensitive lookup ///Thrown if mapping space is not valid internal override Map GetMap(string identity, DataSpace typeSpace, bool ignoreCase) { Map map; if (!this.TryGetMap(identity, typeSpace, ignoreCase, out map)) { throw new InvalidOperationException(System.Data.Entity.Strings.Mapping_Object_InvalidType(identity)); } return map; } ////// Search for a Mapping metadata with the specified type key. /// /// identity of the type /// The dataspace that the type for which map needs to be returned belongs to /// true for case-insensitive lookup /// ///Returns false if no match found. internal override bool TryGetMap(string identity, DataSpace typeSpace, bool ignoreCase, out Map map) { EdmType cdmType = null; EdmType clrType = null; if (typeSpace == DataSpace.CSpace) { if (ignoreCase) { // Get the correct casing of the identity first if we are asked to do ignore case if (!m_edmCollection.TryGetItem(identity, true, out cdmType)) { map = null; return false; } identity = cdmType.Identity; } int index; if (cdmTypeIndexes.TryGetValue(identity, out index)) { map = (Map)this[index]; return true; } if (cdmType != null || m_edmCollection.TryGetItem (identity, ignoreCase, out cdmType)) { // If the mapping is not already loaded, then get the mapping ospace type m_objectCollection.TryGetOSpaceType(cdmType, out clrType); } } else if (typeSpace == DataSpace.OSpace) { if (ignoreCase) { // Get the correct casing of the identity first if we are asked to do ignore case if (!m_objectCollection.TryGetItem (identity, true, out clrType)) { map = null; return false; } identity = clrType.Identity; } int index; if (clrTypeIndexes.TryGetValue(identity, out index)) { map = (Map)this[index]; return true; } if (clrType != null || m_objectCollection.TryGetItem (identity, ignoreCase, out clrType)) { // If the mapping is not already loaded, get the mapping cspace type string cspaceTypeName = ObjectItemCollection.TryGetMappingCSpaceTypeIdentity(clrType); m_edmCollection.TryGetItem (cspaceTypeName, out cdmType); } } if ((clrType == null) || (cdmType == null)) { map = null; return false; } else { map = this.GetDefaultMapping(cdmType, clrType); return true; } } /// /// Search for a Mapping metadata with the specified type key. /// /// identity of the type /// The dataspace that the type for which map needs to be returned belongs to ///Thrown if mapping space is not valid internal override Map GetMap(string identity, DataSpace typeSpace) { return this.GetMap(identity, typeSpace, false /*ignoreCase*/); } ////// Search for a Mapping metadata with the specified type key. /// /// identity of the type /// The dataspace that the type for which map needs to be returned belongs to /// ///Returns false if no match found. internal override bool TryGetMap(string identity, DataSpace typeSpace, out Map map) { return this.TryGetMap(identity, typeSpace, false /*ignoreCase*/, out map); } ////// Search for a Mapping metadata with the specified type key. /// /// internal override Map GetMap(GlobalItem item) { EntityUtil.CheckArgumentNull(item, "item"); Map map; if (!this.TryGetMap(item, out map)) { throw new InvalidOperationException(System.Data.Entity.Strings.Mapping_Object_InvalidType(item.Identity)); } return map; } ////// Search for a Mapping metadata with the specified type key. /// /// /// ///Returns false if no match found. internal override bool TryGetMap(GlobalItem item, out Map map) { if (item == null) { map = null; return false; } DataSpace typeSpace = item.DataSpace; //For transient types just create a map on fly and return EdmType edmType = item as EdmType; if (edmType != null) { if (Helper.IsTransientType(edmType)) { map = GetOCMapForTransientType(edmType, typeSpace); if (map != null) { return true; } else { return false; } } } return this.TryGetMap(item.Identity, typeSpace, out map); } ////// The method creates a default mapping between two TypeMetadatas - one in /// C space and one in O space. The precondition for calling this method is that /// the type in Object space contains the members with the same name as those of defined in /// C space. It is not required the otherway. /// /// /// private Map GetDefaultMapping(EdmType cdmType, EdmType clrType) { Debug.Assert((cdmType != null) && (clrType != null)); return LoadObjectMapping(cdmType, clrType, this); } private Map GetOCMapForTransientType(EdmType edmType, DataSpace typeSpace) { Debug.Assert(typeSpace == DataSpace.CSpace || typeSpace == DataSpace.OSpace || Helper.IsRowType(edmType) || Helper.IsCollectionType(edmType)); EdmType clrType = null; EdmType cdmType = null; int index = -1; if (typeSpace != DataSpace.OSpace) { if (cdmTypeIndexes.TryGetValue(edmType.Identity, out index)) { return (Map)this[index]; } else { cdmType = edmType; clrType = ConvertCSpaceToOSpaceType(edmType); } } else if (typeSpace == DataSpace.OSpace) { if (clrTypeIndexes.TryGetValue(edmType.Identity, out index)) { return (Map)this[index]; } else { clrType = edmType; cdmType = ConvertOSpaceToCSpaceType(clrType); } } ObjectTypeMapping typeMapping = new ObjectTypeMapping(clrType, cdmType); if (BuiltInTypeKind.RowType == edmType.BuiltInTypeKind) { RowType clrRowType = (RowType)clrType; RowType edmRowType = (RowType)cdmType; Debug.Assert(clrRowType.Properties.Count == edmRowType.Properties.Count, "Property count mismatch"); for (int idx = 0; idx < clrRowType.Properties.Count; idx++) { typeMapping.AddMemberMap(new ObjectPropertyMapping(edmRowType.Properties[idx], clrRowType.Properties[idx])); } } if ( (!cdmTypeIndexes.ContainsKey(cdmType.Identity)) && (!clrTypeIndexes.ContainsKey(clrType.Identity)) ) { AddInternalMapping(typeMapping); } return typeMapping; } ///Convert CSpace TypeMetadata into OSpace TypeMetadata /// ///OSpace type metadata private EdmType ConvertCSpaceToOSpaceType(EdmType cdmType) { EdmType clrType = null; if (Helper.IsCollectionType(cdmType)) { EdmType elemType = ConvertCSpaceToOSpaceType(((CollectionType)cdmType).TypeUsage.EdmType); clrType = new CollectionType(elemType); } else if (Helper.IsRowType(cdmType)) { ListclrProperties = new List (); foreach (EdmProperty column in ((RowType)cdmType).Properties) { EdmType clrPropertyType = ConvertCSpaceToOSpaceType(column.TypeUsage.EdmType); EdmProperty clrProperty = new EdmProperty(column.Name, TypeUsage.Create(clrPropertyType)); clrProperties.Add(clrProperty); } clrType = new RowType(clrProperties, ((RowType)cdmType).InitializerMetadata); } else if (Helper.IsRefType(cdmType)) { clrType = new RefType((EntityType)ConvertCSpaceToOSpaceType(((RefType)cdmType).ElementType)); } else if (Helper.IsPrimitiveType(cdmType)) { clrType = m_objectCollection.GetMappedPrimitiveType(((PrimitiveType)cdmType).PrimitiveTypeKind); } else { clrType = ((ObjectTypeMapping)GetMap(cdmType)).ClrType; } Debug.Assert((null != clrType), "null converted clr type"); return clrType; } /// Convert CSpace TypeMetadata into OSpace TypeMetadata /// ///OSpace type metadata private EdmType ConvertOSpaceToCSpaceType(EdmType clrType) { EdmType cdmType = null; if (Helper.IsCollectionType(clrType)) { EdmType elemType = ConvertOSpaceToCSpaceType(((CollectionType)clrType).TypeUsage.EdmType); cdmType = new CollectionType(elemType); } else if (Helper.IsRowType(clrType)) { ListcdmProperties = new List (); foreach (EdmProperty column in ((RowType)clrType).Properties) { EdmType cdmPropertyType = ConvertOSpaceToCSpaceType(column.TypeUsage.EdmType); EdmProperty cdmPorperty = new EdmProperty(column.Name, TypeUsage.Create(cdmPropertyType)); cdmProperties.Add(cdmPorperty); } cdmType = new RowType(cdmProperties, ((RowType)clrType).InitializerMetadata); } else if (Helper.IsRefType(clrType)) { cdmType = new RefType((EntityType)(ConvertOSpaceToCSpaceType(((RefType)clrType).ElementType))); } else { cdmType = ((ObjectTypeMapping)GetMap(clrType)).EdmType; } Debug.Assert((null != cdmType), "null converted clr type"); return cdmType; } /// /// checks if the schemaKey refers to the primitive OC mapping schema and if true, /// loads the maps between primitive types /// ///returns the loaded schema if the schema key refers to a primitive schema private void LoadPrimitiveMaps() { // Get all the primitive types from the CSpace and create OCMaps for it IEnumerablecspaceTypes = m_edmCollection.GetPrimitiveTypes(); foreach (PrimitiveType type in cspaceTypes) { PrimitiveType ospaceType = m_objectCollection.GetMappedPrimitiveType(type.PrimitiveTypeKind); Debug.Assert(ospaceType != null, "all primitive type must have been loaded"); this.AddInternalMapping(new ObjectTypeMapping(ospaceType, type)); } } // Add to the cache. If it is already present, then throw an exception private void AddInternalMapping(ObjectTypeMapping objectMap) { string clrName = objectMap.ClrType.Identity; string cdmName = objectMap.EdmType.Identity; int currIndex = this.Count; //Always assume that the first Map for an associated map being added is //the default map for primitive type. Similarly, row and collection types can collide //because their components are primitive types. For other types, //there should be only one map if (clrTypeIndexes.ContainsKey(clrName)) { if (BuiltInTypeKind.PrimitiveType != objectMap.ClrType.BuiltInTypeKind && BuiltInTypeKind.RowType != objectMap.ClrType.BuiltInTypeKind && BuiltInTypeKind.CollectionType != objectMap.ClrType.BuiltInTypeKind) { throw new MappingException(System.Data.Entity.Strings.Mapping_Duplicate_Type_1(clrName)); } } else { clrTypeIndexes.Add(clrName, currIndex); } if (cdmTypeIndexes.ContainsKey(cdmName)) { if (BuiltInTypeKind.PrimitiveType != objectMap.EdmType.BuiltInTypeKind && BuiltInTypeKind.RowType != objectMap.EdmType.BuiltInTypeKind && BuiltInTypeKind.CollectionType != objectMap.EdmType.BuiltInTypeKind) { throw new MappingException(System.Data.Entity.Strings.Mapping_Duplicate_Type_1(clrName)); } } else { cdmTypeIndexes.Add(cdmName, currIndex); } objectMap.DataSpace = DataSpace.OCSpace; base.AddInternal (objectMap); } /// /// The method fills up the children of ObjectMapping. It goes through the /// members in CDM type and finds the member in Object space with the same name /// and creates a member map between them. These member maps are added /// as children of the object mapping. /// /// /// /// internal static ObjectTypeMapping LoadObjectMapping(EdmType cdmType, EdmType objectType, DefaultObjectMappingItemCollection ocItemCollection) { DictionarytypeMappings = new Dictionary (StringComparer.Ordinal); ObjectTypeMapping typeMapping = LoadObjectMapping(cdmType, objectType, ocItemCollection, typeMappings); // If DefaultOCMappingItemCollection is not null, add all the type mappings to the item collection if (ocItemCollection != null) { foreach (ObjectTypeMapping map in typeMappings.Values) { ocItemCollection.AddInternalMapping(map); } } return typeMapping; } private static ObjectTypeMapping LoadObjectMapping(EdmType edmType, EdmType objectType, DefaultObjectMappingItemCollection ocItemCollection, Dictionary typeMappings) { Debug.Assert((edmType != null) && (objectType != null)); Debug.Assert((edmType.BuiltInTypeKind == objectType.BuiltInTypeKind), "The BuiltInTypeKind must be same in LoadObjectMapping"); // Check if both the types are abstract or both of them are not if (edmType.Abstract != objectType.Abstract) { throw new MappingException(System.Data.Entity.Strings.Mapping_AbstractTypeMappingToNonAbstractType(edmType.FullName, objectType.FullName)); } ObjectTypeMapping objectTypeMapping = new ObjectTypeMapping(objectType, edmType); typeMappings.Add(edmType.FullName, objectTypeMapping); if (edmType.BuiltInTypeKind == BuiltInTypeKind.EntityType || edmType.BuiltInTypeKind == BuiltInTypeKind.ComplexType) { LoadEntityTypeOrComplexTypeMapping(objectTypeMapping, edmType, objectType, ocItemCollection, typeMappings); } else { LoadAssociationTypeMapping(objectTypeMapping, edmType, objectType, ocItemCollection, typeMappings); } return objectTypeMapping; } /// /// Tries and get the mapping ospace member for the given edmMember and the ospace type /// /// /// ////// Validates the scalar property on the cspace side and ospace side and creates a new /// ObjectPropertyMapping, if everything maps property /// /// /// /// private static ObjectPropertyMapping LoadScalarPropertyMapping(EdmProperty edmProperty, EdmProperty objectProperty) { Debug.Assert(Helper.IsPrimitiveType(edmProperty.TypeUsage.EdmType), "Only edm scalar properties expected"); Debug.Assert(Helper.IsPrimitiveType(objectProperty.TypeUsage.EdmType), "Only object scalar properties expected"); return new ObjectPropertyMapping(edmProperty, objectProperty); } /// /// Load the entity type or complex type mapping /// /// /// /// /// /// private static void LoadEntityTypeOrComplexTypeMapping(ObjectTypeMapping objectMapping, EdmType edmType, EdmType objectType, DefaultObjectMappingItemCollection ocItemCollection, DictionarytypeMappings) { Debug.Assert(edmType.BuiltInTypeKind == BuiltInTypeKind.EntityType || edmType.BuiltInTypeKind == BuiltInTypeKind.ComplexType, "Expected Type Encountered in LoadEntityTypeOrComplexTypeMapping"); Debug.Assert((edmType.BuiltInTypeKind == objectType.BuiltInTypeKind), "The BuiltInTypeKind must be same in LoadEntityTypeOrComplexTypeMapping"); StructuralType cdmStructuralType = (StructuralType)edmType; StructuralType objectStructuralType = (StructuralType)objectType; if (cdmStructuralType.Members.Count != objectStructuralType.Members.Count) { throw new MappingException(System.Data.Entity.Strings.Mapping_Default_OCMapping_Member_Count_Mismatch_2( edmType.FullName, objectType.FullName)); } //Go through the CDMMembers and find the corresponding member in Object space //and create a member map. foreach (EdmMember edmMember in cdmStructuralType.Members) { EdmMember objectMember = GetObjectMember(edmMember, objectStructuralType); if (Helper.IsEdmProperty(edmMember)) { EdmProperty edmPropertyMember = (EdmProperty)edmMember; EdmProperty edmPropertyObject = (EdmProperty)objectMember; //Depending on the type of member load the member mapping i.e. For complex //members we have to go in and load the child members of the Complex type. if (Helper.IsComplexType(edmMember.TypeUsage.EdmType)) { objectMapping.AddMemberMap( LoadComplexMemberMapping(edmPropertyMember, edmPropertyObject, ocItemCollection, typeMappings)); } else { objectMapping.AddMemberMap( LoadScalarPropertyMapping(edmPropertyMember, edmPropertyObject)); } } else { Debug.Assert(edmMember.BuiltInTypeKind == BuiltInTypeKind.NavigationProperty, "Unexpected Property type encountered"); // For navigation properties, we need to make sure the relationship type on the navigation property is mapped NavigationProperty navigationProperty = (NavigationProperty)edmMember; NavigationProperty objectNavigationProperty = (NavigationProperty)objectMember; LoadTypeMapping(navigationProperty.RelationshipType, objectNavigationProperty.RelationshipType, ocItemCollection, typeMappings); objectMapping.AddMemberMap(new ObjectNavigationPropertyMapping(navigationProperty, objectNavigationProperty)); } } } /// /// Loads Association Type Mapping /// /// /// /// /// /// private static void LoadAssociationTypeMapping(ObjectTypeMapping objectMapping, EdmType edmType, EdmType objectType, DefaultObjectMappingItemCollection ocItemCollection, DictionarytypeMappings) { Debug.Assert(edmType.BuiltInTypeKind == BuiltInTypeKind.AssociationType, "Expected Type Encountered in LoadAssociationTypeMapping"); Debug.Assert((edmType.BuiltInTypeKind == objectType.BuiltInTypeKind), "The BuiltInTypeKind must be same in LoadAssociationTypeMapping"); AssociationType association = (AssociationType)edmType; AssociationType objectAssociation = (AssociationType)objectType; foreach (AssociationEndMember edmEnd in association.AssociationEndMembers) { AssociationEndMember objectEnd = (AssociationEndMember)GetObjectMember(edmEnd, objectAssociation); if (edmEnd.RelationshipMultiplicity != objectEnd.RelationshipMultiplicity) { throw new MappingException(System.Data.Entity.Strings.Mapping_Default_OCMapping_MultiplicityMismatch_6( edmEnd.RelationshipMultiplicity, edmEnd.Name, association.FullName, objectEnd.RelationshipMultiplicity, objectEnd.Name, objectAssociation.FullName)); } Debug.Assert(edmEnd.TypeUsage.EdmType.BuiltInTypeKind == BuiltInTypeKind.RefType, "Ends must be of Ref type"); // GetMap for the entity types for the ends of the relationship type to make sure // the entity type mentioned are valid LoadTypeMapping(((RefType)edmEnd.TypeUsage.EdmType).ElementType, ((RefType)objectEnd.TypeUsage.EdmType).ElementType, ocItemCollection, typeMappings); objectMapping.AddMemberMap(new ObjectAssociationEndMapping(edmEnd, objectEnd)); } } /// /// The method loads the EdmMember mapping for complex members. /// It goes through the CDM members of the Complex Cdm type and /// tries to find the corresponding members in Complex Clr type. /// /// /// /// /// ///private static ObjectComplexPropertyMapping LoadComplexMemberMapping(EdmProperty containingEdmMember, EdmProperty containingClrMember, DefaultObjectMappingItemCollection ocItemCollection, Dictionary typeMappings) { Debug.Assert(containingEdmMember.TypeUsage.EdmType.BuiltInTypeKind == BuiltInTypeKind.ComplexType, "edm member declaringType must be of complexType"); Debug.Assert(containingClrMember.TypeUsage.EdmType.BuiltInTypeKind == BuiltInTypeKind.ComplexType, "clr member declaringType must be of complexType"); ComplexType edmComplexType = (ComplexType)containingEdmMember.TypeUsage.EdmType; ComplexType objectComplexType = (ComplexType)containingClrMember.TypeUsage.EdmType; // Get the type mapping for the complex type ObjectTypeMapping complexTypeMapping = LoadTypeMapping(edmComplexType, objectComplexType, ocItemCollection, typeMappings); //Go through the CDMMembers and find the corresponding member in Object space //and create a member map. return new ObjectComplexPropertyMapping(containingEdmMember, containingClrMember, complexTypeMapping); } private static ObjectTypeMapping LoadTypeMapping(EdmType edmType, EdmType objectType, DefaultObjectMappingItemCollection ocItemCollection, Dictionary typeMappings) { ObjectTypeMapping objectTypeMapping; //First, check in the type mappings to find out if the mapping is already present if (typeMappings.TryGetValue(edmType.FullName, out objectTypeMapping)) { return objectTypeMapping; } if (ocItemCollection != null) { ObjectTypeMapping typeMapping; if (ocItemCollection.ContainsMap(edmType, out typeMapping)) { return (ObjectTypeMapping)typeMapping; } } // If the type mapping is not already loaded, then load it return LoadObjectMapping(edmType, objectType, ocItemCollection, typeMappings); } private bool ContainsMap(GlobalItem cspaceItem, out ObjectTypeMapping map) { Debug.Assert(cspaceItem.DataSpace == DataSpace.CSpace, "ContainsMap: It must be a CSpace item"); int index; if (cdmTypeIndexes.TryGetValue(cspaceItem.Identity, out index)) { map = (ObjectTypeMapping)this[index]; return true; } map = null; return false; } #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.Diagnostics; using System.Collections; using System.Collections.Generic; using System.Xml.XPath; using System.Xml; using System.Xml.Schema; using System.Data.Metadata.Edm; using System.Data.Entity; namespace System.Data.Mapping { ////// The class creates a default OCMapping between a TypeMetadata in O space /// and an TypeMetadata in Edm space. The loader expects that for each member in /// C space type there exists a member in O space type that has the same name. The member maps will be stored in /// C space member order. /// internal class DefaultObjectMappingItemCollection : MappingItemCollection { #region Constructors ////// Constrcutor to create an instance of DefaultObjectMappingItemCollection. /// To start with we will create a Schema under which maps will be created. /// /// /// public DefaultObjectMappingItemCollection(EdmItemCollection edmCollection, ObjectItemCollection objectCollection) : base(DataSpace.OCSpace) { EntityUtil.CheckArgumentNull(edmCollection, "edmCollection"); EntityUtil.CheckArgumentNull(objectCollection, "objectCollection"); this.m_edmCollection = edmCollection; this.m_objectCollection = objectCollection; LoadPrimitiveMaps(); } #endregion #region Fields private ObjectItemCollection m_objectCollection; private EdmItemCollection m_edmCollection; private DictionaryclrTypeIndexes = new Dictionary (StringComparer.Ordinal); //Indexes into the type mappings collection based on clr type name private Dictionary cdmTypeIndexes = new Dictionary (StringComparer.Ordinal); //Indexes into the type mappings collection based on clr type name #endregion #region Methods /// /// Search for a Mapping metadata with the specified type key. /// /// identity of the type /// The dataspace that the type for which map needs to be returned belongs to /// true for case-insensitive lookup ///Thrown if mapping space is not valid internal override Map GetMap(string identity, DataSpace typeSpace, bool ignoreCase) { Map map; if (!this.TryGetMap(identity, typeSpace, ignoreCase, out map)) { throw new InvalidOperationException(System.Data.Entity.Strings.Mapping_Object_InvalidType(identity)); } return map; } ////// Search for a Mapping metadata with the specified type key. /// /// identity of the type /// The dataspace that the type for which map needs to be returned belongs to /// true for case-insensitive lookup /// ///Returns false if no match found. internal override bool TryGetMap(string identity, DataSpace typeSpace, bool ignoreCase, out Map map) { EdmType cdmType = null; EdmType clrType = null; if (typeSpace == DataSpace.CSpace) { if (ignoreCase) { // Get the correct casing of the identity first if we are asked to do ignore case if (!m_edmCollection.TryGetItem(identity, true, out cdmType)) { map = null; return false; } identity = cdmType.Identity; } int index; if (cdmTypeIndexes.TryGetValue(identity, out index)) { map = (Map)this[index]; return true; } if (cdmType != null || m_edmCollection.TryGetItem (identity, ignoreCase, out cdmType)) { // If the mapping is not already loaded, then get the mapping ospace type m_objectCollection.TryGetOSpaceType(cdmType, out clrType); } } else if (typeSpace == DataSpace.OSpace) { if (ignoreCase) { // Get the correct casing of the identity first if we are asked to do ignore case if (!m_objectCollection.TryGetItem (identity, true, out clrType)) { map = null; return false; } identity = clrType.Identity; } int index; if (clrTypeIndexes.TryGetValue(identity, out index)) { map = (Map)this[index]; return true; } if (clrType != null || m_objectCollection.TryGetItem (identity, ignoreCase, out clrType)) { // If the mapping is not already loaded, get the mapping cspace type string cspaceTypeName = ObjectItemCollection.TryGetMappingCSpaceTypeIdentity(clrType); m_edmCollection.TryGetItem (cspaceTypeName, out cdmType); } } if ((clrType == null) || (cdmType == null)) { map = null; return false; } else { map = this.GetDefaultMapping(cdmType, clrType); return true; } } /// /// Search for a Mapping metadata with the specified type key. /// /// identity of the type /// The dataspace that the type for which map needs to be returned belongs to ///Thrown if mapping space is not valid internal override Map GetMap(string identity, DataSpace typeSpace) { return this.GetMap(identity, typeSpace, false /*ignoreCase*/); } ////// Search for a Mapping metadata with the specified type key. /// /// identity of the type /// The dataspace that the type for which map needs to be returned belongs to /// ///Returns false if no match found. internal override bool TryGetMap(string identity, DataSpace typeSpace, out Map map) { return this.TryGetMap(identity, typeSpace, false /*ignoreCase*/, out map); } ////// Search for a Mapping metadata with the specified type key. /// /// internal override Map GetMap(GlobalItem item) { EntityUtil.CheckArgumentNull(item, "item"); Map map; if (!this.TryGetMap(item, out map)) { throw new InvalidOperationException(System.Data.Entity.Strings.Mapping_Object_InvalidType(item.Identity)); } return map; } ////// Search for a Mapping metadata with the specified type key. /// /// /// ///Returns false if no match found. internal override bool TryGetMap(GlobalItem item, out Map map) { if (item == null) { map = null; return false; } DataSpace typeSpace = item.DataSpace; //For transient types just create a map on fly and return EdmType edmType = item as EdmType; if (edmType != null) { if (Helper.IsTransientType(edmType)) { map = GetOCMapForTransientType(edmType, typeSpace); if (map != null) { return true; } else { return false; } } } return this.TryGetMap(item.Identity, typeSpace, out map); } ////// The method creates a default mapping between two TypeMetadatas - one in /// C space and one in O space. The precondition for calling this method is that /// the type in Object space contains the members with the same name as those of defined in /// C space. It is not required the otherway. /// /// /// private Map GetDefaultMapping(EdmType cdmType, EdmType clrType) { Debug.Assert((cdmType != null) && (clrType != null)); return LoadObjectMapping(cdmType, clrType, this); } private Map GetOCMapForTransientType(EdmType edmType, DataSpace typeSpace) { Debug.Assert(typeSpace == DataSpace.CSpace || typeSpace == DataSpace.OSpace || Helper.IsRowType(edmType) || Helper.IsCollectionType(edmType)); EdmType clrType = null; EdmType cdmType = null; int index = -1; if (typeSpace != DataSpace.OSpace) { if (cdmTypeIndexes.TryGetValue(edmType.Identity, out index)) { return (Map)this[index]; } else { cdmType = edmType; clrType = ConvertCSpaceToOSpaceType(edmType); } } else if (typeSpace == DataSpace.OSpace) { if (clrTypeIndexes.TryGetValue(edmType.Identity, out index)) { return (Map)this[index]; } else { clrType = edmType; cdmType = ConvertOSpaceToCSpaceType(clrType); } } ObjectTypeMapping typeMapping = new ObjectTypeMapping(clrType, cdmType); if (BuiltInTypeKind.RowType == edmType.BuiltInTypeKind) { RowType clrRowType = (RowType)clrType; RowType edmRowType = (RowType)cdmType; Debug.Assert(clrRowType.Properties.Count == edmRowType.Properties.Count, "Property count mismatch"); for (int idx = 0; idx < clrRowType.Properties.Count; idx++) { typeMapping.AddMemberMap(new ObjectPropertyMapping(edmRowType.Properties[idx], clrRowType.Properties[idx])); } } if ( (!cdmTypeIndexes.ContainsKey(cdmType.Identity)) && (!clrTypeIndexes.ContainsKey(clrType.Identity)) ) { AddInternalMapping(typeMapping); } return typeMapping; } ///Convert CSpace TypeMetadata into OSpace TypeMetadata /// ///OSpace type metadata private EdmType ConvertCSpaceToOSpaceType(EdmType cdmType) { EdmType clrType = null; if (Helper.IsCollectionType(cdmType)) { EdmType elemType = ConvertCSpaceToOSpaceType(((CollectionType)cdmType).TypeUsage.EdmType); clrType = new CollectionType(elemType); } else if (Helper.IsRowType(cdmType)) { ListclrProperties = new List (); foreach (EdmProperty column in ((RowType)cdmType).Properties) { EdmType clrPropertyType = ConvertCSpaceToOSpaceType(column.TypeUsage.EdmType); EdmProperty clrProperty = new EdmProperty(column.Name, TypeUsage.Create(clrPropertyType)); clrProperties.Add(clrProperty); } clrType = new RowType(clrProperties, ((RowType)cdmType).InitializerMetadata); } else if (Helper.IsRefType(cdmType)) { clrType = new RefType((EntityType)ConvertCSpaceToOSpaceType(((RefType)cdmType).ElementType)); } else if (Helper.IsPrimitiveType(cdmType)) { clrType = m_objectCollection.GetMappedPrimitiveType(((PrimitiveType)cdmType).PrimitiveTypeKind); } else { clrType = ((ObjectTypeMapping)GetMap(cdmType)).ClrType; } Debug.Assert((null != clrType), "null converted clr type"); return clrType; } /// Convert CSpace TypeMetadata into OSpace TypeMetadata /// ///OSpace type metadata private EdmType ConvertOSpaceToCSpaceType(EdmType clrType) { EdmType cdmType = null; if (Helper.IsCollectionType(clrType)) { EdmType elemType = ConvertOSpaceToCSpaceType(((CollectionType)clrType).TypeUsage.EdmType); cdmType = new CollectionType(elemType); } else if (Helper.IsRowType(clrType)) { ListcdmProperties = new List (); foreach (EdmProperty column in ((RowType)clrType).Properties) { EdmType cdmPropertyType = ConvertOSpaceToCSpaceType(column.TypeUsage.EdmType); EdmProperty cdmPorperty = new EdmProperty(column.Name, TypeUsage.Create(cdmPropertyType)); cdmProperties.Add(cdmPorperty); } cdmType = new RowType(cdmProperties, ((RowType)clrType).InitializerMetadata); } else if (Helper.IsRefType(clrType)) { cdmType = new RefType((EntityType)(ConvertOSpaceToCSpaceType(((RefType)clrType).ElementType))); } else { cdmType = ((ObjectTypeMapping)GetMap(clrType)).EdmType; } Debug.Assert((null != cdmType), "null converted clr type"); return cdmType; } /// /// checks if the schemaKey refers to the primitive OC mapping schema and if true, /// loads the maps between primitive types /// ///returns the loaded schema if the schema key refers to a primitive schema private void LoadPrimitiveMaps() { // Get all the primitive types from the CSpace and create OCMaps for it IEnumerablecspaceTypes = m_edmCollection.GetPrimitiveTypes(); foreach (PrimitiveType type in cspaceTypes) { PrimitiveType ospaceType = m_objectCollection.GetMappedPrimitiveType(type.PrimitiveTypeKind); Debug.Assert(ospaceType != null, "all primitive type must have been loaded"); this.AddInternalMapping(new ObjectTypeMapping(ospaceType, type)); } } // Add to the cache. If it is already present, then throw an exception private void AddInternalMapping(ObjectTypeMapping objectMap) { string clrName = objectMap.ClrType.Identity; string cdmName = objectMap.EdmType.Identity; int currIndex = this.Count; //Always assume that the first Map for an associated map being added is //the default map for primitive type. Similarly, row and collection types can collide //because their components are primitive types. For other types, //there should be only one map if (clrTypeIndexes.ContainsKey(clrName)) { if (BuiltInTypeKind.PrimitiveType != objectMap.ClrType.BuiltInTypeKind && BuiltInTypeKind.RowType != objectMap.ClrType.BuiltInTypeKind && BuiltInTypeKind.CollectionType != objectMap.ClrType.BuiltInTypeKind) { throw new MappingException(System.Data.Entity.Strings.Mapping_Duplicate_Type_1(clrName)); } } else { clrTypeIndexes.Add(clrName, currIndex); } if (cdmTypeIndexes.ContainsKey(cdmName)) { if (BuiltInTypeKind.PrimitiveType != objectMap.EdmType.BuiltInTypeKind && BuiltInTypeKind.RowType != objectMap.EdmType.BuiltInTypeKind && BuiltInTypeKind.CollectionType != objectMap.EdmType.BuiltInTypeKind) { throw new MappingException(System.Data.Entity.Strings.Mapping_Duplicate_Type_1(clrName)); } } else { cdmTypeIndexes.Add(cdmName, currIndex); } objectMap.DataSpace = DataSpace.OCSpace; base.AddInternal (objectMap); } /// /// The method fills up the children of ObjectMapping. It goes through the /// members in CDM type and finds the member in Object space with the same name /// and creates a member map between them. These member maps are added /// as children of the object mapping. /// /// /// /// internal static ObjectTypeMapping LoadObjectMapping(EdmType cdmType, EdmType objectType, DefaultObjectMappingItemCollection ocItemCollection) { DictionarytypeMappings = new Dictionary (StringComparer.Ordinal); ObjectTypeMapping typeMapping = LoadObjectMapping(cdmType, objectType, ocItemCollection, typeMappings); // If DefaultOCMappingItemCollection is not null, add all the type mappings to the item collection if (ocItemCollection != null) { foreach (ObjectTypeMapping map in typeMappings.Values) { ocItemCollection.AddInternalMapping(map); } } return typeMapping; } private static ObjectTypeMapping LoadObjectMapping(EdmType edmType, EdmType objectType, DefaultObjectMappingItemCollection ocItemCollection, Dictionary typeMappings) { Debug.Assert((edmType != null) && (objectType != null)); Debug.Assert((edmType.BuiltInTypeKind == objectType.BuiltInTypeKind), "The BuiltInTypeKind must be same in LoadObjectMapping"); // Check if both the types are abstract or both of them are not if (edmType.Abstract != objectType.Abstract) { throw new MappingException(System.Data.Entity.Strings.Mapping_AbstractTypeMappingToNonAbstractType(edmType.FullName, objectType.FullName)); } ObjectTypeMapping objectTypeMapping = new ObjectTypeMapping(objectType, edmType); typeMappings.Add(edmType.FullName, objectTypeMapping); if (edmType.BuiltInTypeKind == BuiltInTypeKind.EntityType || edmType.BuiltInTypeKind == BuiltInTypeKind.ComplexType) { LoadEntityTypeOrComplexTypeMapping(objectTypeMapping, edmType, objectType, ocItemCollection, typeMappings); } else { LoadAssociationTypeMapping(objectTypeMapping, edmType, objectType, ocItemCollection, typeMappings); } return objectTypeMapping; } /// /// Tries and get the mapping ospace member for the given edmMember and the ospace type /// /// /// ////// Validates the scalar property on the cspace side and ospace side and creates a new /// ObjectPropertyMapping, if everything maps property /// /// /// /// private static ObjectPropertyMapping LoadScalarPropertyMapping(EdmProperty edmProperty, EdmProperty objectProperty) { Debug.Assert(Helper.IsPrimitiveType(edmProperty.TypeUsage.EdmType), "Only edm scalar properties expected"); Debug.Assert(Helper.IsPrimitiveType(objectProperty.TypeUsage.EdmType), "Only object scalar properties expected"); return new ObjectPropertyMapping(edmProperty, objectProperty); } /// /// Load the entity type or complex type mapping /// /// /// /// /// /// private static void LoadEntityTypeOrComplexTypeMapping(ObjectTypeMapping objectMapping, EdmType edmType, EdmType objectType, DefaultObjectMappingItemCollection ocItemCollection, DictionarytypeMappings) { Debug.Assert(edmType.BuiltInTypeKind == BuiltInTypeKind.EntityType || edmType.BuiltInTypeKind == BuiltInTypeKind.ComplexType, "Expected Type Encountered in LoadEntityTypeOrComplexTypeMapping"); Debug.Assert((edmType.BuiltInTypeKind == objectType.BuiltInTypeKind), "The BuiltInTypeKind must be same in LoadEntityTypeOrComplexTypeMapping"); StructuralType cdmStructuralType = (StructuralType)edmType; StructuralType objectStructuralType = (StructuralType)objectType; if (cdmStructuralType.Members.Count != objectStructuralType.Members.Count) { throw new MappingException(System.Data.Entity.Strings.Mapping_Default_OCMapping_Member_Count_Mismatch_2( edmType.FullName, objectType.FullName)); } //Go through the CDMMembers and find the corresponding member in Object space //and create a member map. foreach (EdmMember edmMember in cdmStructuralType.Members) { EdmMember objectMember = GetObjectMember(edmMember, objectStructuralType); if (Helper.IsEdmProperty(edmMember)) { EdmProperty edmPropertyMember = (EdmProperty)edmMember; EdmProperty edmPropertyObject = (EdmProperty)objectMember; //Depending on the type of member load the member mapping i.e. For complex //members we have to go in and load the child members of the Complex type. if (Helper.IsComplexType(edmMember.TypeUsage.EdmType)) { objectMapping.AddMemberMap( LoadComplexMemberMapping(edmPropertyMember, edmPropertyObject, ocItemCollection, typeMappings)); } else { objectMapping.AddMemberMap( LoadScalarPropertyMapping(edmPropertyMember, edmPropertyObject)); } } else { Debug.Assert(edmMember.BuiltInTypeKind == BuiltInTypeKind.NavigationProperty, "Unexpected Property type encountered"); // For navigation properties, we need to make sure the relationship type on the navigation property is mapped NavigationProperty navigationProperty = (NavigationProperty)edmMember; NavigationProperty objectNavigationProperty = (NavigationProperty)objectMember; LoadTypeMapping(navigationProperty.RelationshipType, objectNavigationProperty.RelationshipType, ocItemCollection, typeMappings); objectMapping.AddMemberMap(new ObjectNavigationPropertyMapping(navigationProperty, objectNavigationProperty)); } } } /// /// Loads Association Type Mapping /// /// /// /// /// /// private static void LoadAssociationTypeMapping(ObjectTypeMapping objectMapping, EdmType edmType, EdmType objectType, DefaultObjectMappingItemCollection ocItemCollection, DictionarytypeMappings) { Debug.Assert(edmType.BuiltInTypeKind == BuiltInTypeKind.AssociationType, "Expected Type Encountered in LoadAssociationTypeMapping"); Debug.Assert((edmType.BuiltInTypeKind == objectType.BuiltInTypeKind), "The BuiltInTypeKind must be same in LoadAssociationTypeMapping"); AssociationType association = (AssociationType)edmType; AssociationType objectAssociation = (AssociationType)objectType; foreach (AssociationEndMember edmEnd in association.AssociationEndMembers) { AssociationEndMember objectEnd = (AssociationEndMember)GetObjectMember(edmEnd, objectAssociation); if (edmEnd.RelationshipMultiplicity != objectEnd.RelationshipMultiplicity) { throw new MappingException(System.Data.Entity.Strings.Mapping_Default_OCMapping_MultiplicityMismatch_6( edmEnd.RelationshipMultiplicity, edmEnd.Name, association.FullName, objectEnd.RelationshipMultiplicity, objectEnd.Name, objectAssociation.FullName)); } Debug.Assert(edmEnd.TypeUsage.EdmType.BuiltInTypeKind == BuiltInTypeKind.RefType, "Ends must be of Ref type"); // GetMap for the entity types for the ends of the relationship type to make sure // the entity type mentioned are valid LoadTypeMapping(((RefType)edmEnd.TypeUsage.EdmType).ElementType, ((RefType)objectEnd.TypeUsage.EdmType).ElementType, ocItemCollection, typeMappings); objectMapping.AddMemberMap(new ObjectAssociationEndMapping(edmEnd, objectEnd)); } } /// /// The method loads the EdmMember mapping for complex members. /// It goes through the CDM members of the Complex Cdm type and /// tries to find the corresponding members in Complex Clr type. /// /// /// /// /// ///private static ObjectComplexPropertyMapping LoadComplexMemberMapping(EdmProperty containingEdmMember, EdmProperty containingClrMember, DefaultObjectMappingItemCollection ocItemCollection, Dictionary typeMappings) { Debug.Assert(containingEdmMember.TypeUsage.EdmType.BuiltInTypeKind == BuiltInTypeKind.ComplexType, "edm member declaringType must be of complexType"); Debug.Assert(containingClrMember.TypeUsage.EdmType.BuiltInTypeKind == BuiltInTypeKind.ComplexType, "clr member declaringType must be of complexType"); ComplexType edmComplexType = (ComplexType)containingEdmMember.TypeUsage.EdmType; ComplexType objectComplexType = (ComplexType)containingClrMember.TypeUsage.EdmType; // Get the type mapping for the complex type ObjectTypeMapping complexTypeMapping = LoadTypeMapping(edmComplexType, objectComplexType, ocItemCollection, typeMappings); //Go through the CDMMembers and find the corresponding member in Object space //and create a member map. return new ObjectComplexPropertyMapping(containingEdmMember, containingClrMember, complexTypeMapping); } private static ObjectTypeMapping LoadTypeMapping(EdmType edmType, EdmType objectType, DefaultObjectMappingItemCollection ocItemCollection, Dictionary typeMappings) { ObjectTypeMapping objectTypeMapping; //First, check in the type mappings to find out if the mapping is already present if (typeMappings.TryGetValue(edmType.FullName, out objectTypeMapping)) { return objectTypeMapping; } if (ocItemCollection != null) { ObjectTypeMapping typeMapping; if (ocItemCollection.ContainsMap(edmType, out typeMapping)) { return (ObjectTypeMapping)typeMapping; } } // If the type mapping is not already loaded, then load it return LoadObjectMapping(edmType, objectType, ocItemCollection, typeMappings); } private bool ContainsMap(GlobalItem cspaceItem, out ObjectTypeMapping map) { Debug.Assert(cspaceItem.DataSpace == DataSpace.CSpace, "ContainsMap: It must be a CSpace item"); int index; if (cdmTypeIndexes.TryGetValue(cspaceItem.Identity, out index)) { map = (ObjectTypeMapping)this[index]; return true; } map = null; return false; } #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DataRelationCollection.cs
- DataGridCell.cs
- SqlUDTStorage.cs
- ListControlBuilder.cs
- Vector3DConverter.cs
- TableDetailsCollection.cs
- ControlCachePolicy.cs
- recordstatescratchpad.cs
- IMembershipProvider.cs
- ConnectionPoint.cs
- ResourcesChangeInfo.cs
- StackBuilderSink.cs
- COMException.cs
- _AutoWebProxyScriptEngine.cs
- IChannel.cs
- MessageContractImporter.cs
- AsymmetricSignatureFormatter.cs
- IIS7WorkerRequest.cs
- EventProviderClassic.cs
- ActivationServices.cs
- DocumentOrderQuery.cs
- DataGridViewHitTestInfo.cs
- AxWrapperGen.cs
- SqlDataSourceEnumerator.cs
- DataGridViewRowsAddedEventArgs.cs
- StorageEndPropertyMapping.cs
- Partitioner.cs
- BuildProviderAppliesToAttribute.cs
- XPathNodePointer.cs
- HwndSourceKeyboardInputSite.cs
- ByteKeyFrameCollection.cs
- HitTestWithGeometryDrawingContextWalker.cs
- MimeTypeMapper.cs
- OdbcParameter.cs
- AdPostCacheSubstitution.cs
- ToolStripGrip.cs
- TraceLevelStore.cs
- ConfigurationStrings.cs
- TextAnchor.cs
- InfoCardRSAPKCS1KeyExchangeDeformatter.cs
- WorkflowInvoker.cs
- RectAnimation.cs
- InlineUIContainer.cs
- CodeDOMUtility.cs
- DataError.cs
- TextTreePropertyUndoUnit.cs
- ComponentManagerBroker.cs
- ResourcesChangeInfo.cs
- ApplicationServiceManager.cs
- SafePipeHandle.cs
- ClientCultureInfo.cs
- InternalTypeHelper.cs
- RuleInfoComparer.cs
- SelectionChangedEventArgs.cs
- URL.cs
- SqlUtils.cs
- COM2IPerPropertyBrowsingHandler.cs
- SoapAttributeAttribute.cs
- Lasso.cs
- UIntPtr.cs
- ServiceHttpModule.cs
- DocumentXmlWriter.cs
- MdiWindowListItemConverter.cs
- ResourceBinder.cs
- XmlObjectSerializerReadContext.cs
- SwitchExpression.cs
- DynamicDocumentPaginator.cs
- lengthconverter.cs
- AuthenticatingEventArgs.cs
- TableItemStyle.cs
- InlineUIContainer.cs
- EventManager.cs
- EventListener.cs
- ItemList.cs
- Serializer.cs
- IndexedGlyphRun.cs
- StoreItemCollection.Loader.cs
- XPathItem.cs
- ArgumentNullException.cs
- QueryRewriter.cs
- DockAndAnchorLayout.cs
- SemanticKeyElement.cs
- PageVisual.cs
- RegisteredScript.cs
- SupportsEventValidationAttribute.cs
- EnumMember.cs
- ProcessingInstructionAction.cs
- SmiEventSink_DeferedProcessing.cs
- Bitmap.cs
- LinearGradientBrush.cs
- MailWriter.cs
- BookmarkScopeInfo.cs
- Dictionary.cs
- DataGridViewComboBoxColumn.cs
- SQLInt64.cs
- TypeDescriptor.cs
- WindowsUpDown.cs
- ScaleTransform3D.cs
- Pen.cs
- TreePrinter.cs