/// <summary> /// Updates the flattened SSDL. /// </summary> /// <param name="ssdlDocument">The SSDL document.</param> /// <param name="tableMappings">The table mappings.</param> internal void UpdateFlattenedSsdl(XmlDocument ssdlDocument, TableMappingCollection tableMappings) { // Process custom resource types. foreach (ResourceType resourceType in this.ResourceTypes) { resourceType.UpdateFlattenedSsdl(ssdlDocument, tableMappings); } // Process custom associations. foreach (Association association in this.Associations) { association.UpdateFlattenedSsdl(ssdlDocument, tableMappings); } Association associationResourceHasFile = (from association in this.Parent.Modules[DataModellingResources.ZentityCore].Associations where association.ObjectRole == typeof(File).Name select association).FirstOrDefault(); if (associationResourceHasFile != null) { foreach (ResourceType resourceType in this.ResourceTypes) { associationResourceHasFile.UpdateFlattenedSsdlForFile(ssdlDocument, resourceType); } } }
internal void UpdateSsdl(XmlDocument ssdlDocument, TableMappingCollection tableMappings) { foreach (ScalarProperty property in this.ScalarProperties) { property.UpdateSsdl(ssdlDocument, tableMappings); } #region Create CUD Functions. XmlNamespaceManager nsMgr = new XmlNamespaceManager(ssdlDocument.NameTable); nsMgr.AddNamespace(CoreResources.SSDLNamespacePrefix, CoreResources.SSDLSchemaNameSpace); XmlElement schemaElement = ssdlDocument.SelectSingleNode( CoreResources.XPathSSDLSchema, nsMgr) as XmlElement; List <string> parameters = new List <string>(); List <string> deleteParameters = new List <string>(); deleteParameters.Add(CoreResources.Id); deleteParameters.Add(CoreResources.DataTypeUniqueidentifier); deleteParameters.Add(CoreResources.In); ResourceType tempType = this; while (tempType != null) { foreach (ScalarProperty scalarProperty in tempType.ScalarProperties) { parameters.Add(scalarProperty.Name); parameters.Add(Utilities.GetSQLType(scalarProperty.DataType)); parameters.Add(CoreResources.In); } foreach (NavigationProperty navigationProperty in tempType.NavigationProperties) { if (tableMappings.GetColumnMappingByPropertyId(navigationProperty.Id) != null) { parameters.Add(navigationProperty.Name); parameters.Add(CoreResources.DataTypeUniqueidentifier); parameters.Add(CoreResources.In); deleteParameters.Add(navigationProperty.Name); deleteParameters.Add(CoreResources.DataTypeUniqueidentifier); deleteParameters.Add(CoreResources.In); } } tempType = tempType.BaseType; } Utilities.AddSsdlFunction(schemaElement, this.InsertProcedureName, false, false, false, false, CoreResources.AllowImplicitConversion, CoreResources.Core, parameters.ToArray()); Utilities.AddSsdlFunction(schemaElement, this.UpdateProcedureName, false, false, false, false, CoreResources.AllowImplicitConversion, CoreResources.Core, parameters.ToArray()); Utilities.AddSsdlFunction(schemaElement, this.DeleteProcedureName, false, false, false, false, CoreResources.AllowImplicitConversion, CoreResources.Core, deleteParameters.ToArray()); #endregion }
/// <summary> /// Updates the flattened MSL. /// </summary> /// <param name="mslDocument">The MSL document.</param> /// <param name="tableMappings">The table mappings.</param> /// <param name="discriminators">The discriminators.</param> /// <param name="storageSchemaName">Name of the storage schema.</param> internal void UpdateFlattenedMsl(XmlDocument mslDocument, TableMappingCollection tableMappings, Dictionary <Guid, int> discriminators, string storageSchemaName) { // Sort the resource types. We copy over mapping fragments from base type to the // derived type and thus it is required that the base type is processed before // derived types. List <ResourceType> sortedTypes = DataModel.SortByHierarchy(this.ResourceTypes.ToList()); // Process Resource Types. foreach (ResourceType resourceType in sortedTypes) { resourceType.UpdateFlattenedMsl(mslDocument, tableMappings, discriminators, storageSchemaName); } // Process Associations. foreach (Association association in this.Associations) { association.UpdateFlattenedMsl(mslDocument, tableMappings, storageSchemaName); } Association associationResourceHasFile = (from association in this.Parent.Modules[DataModellingResources.ZentityCore].Associations where association.ObjectRole == typeof(File).Name select association).FirstOrDefault(); if (associationResourceHasFile != null) { foreach (ResourceType resourceType in this.ResourceTypes) { associationResourceHasFile.UpdateFlattenedMslForFile(mslDocument, resourceType, storageSchemaName); } } }
/// <summary> /// Clones this instance. /// </summary> /// <returns>Table mapping collection</returns> internal TableMappingCollection Clone() { // Do a deep copy. TableMappingCollection newTableMappings = new TableMappingCollection(); foreach (TableMapping sourceTableMapping in this) { TableMapping targetTableMapping = new TableMapping { TableName = sourceTableMapping.TableName }; newTableMappings.Add(targetTableMapping); foreach (ColumnMapping sourceColumnMapping in sourceTableMapping.ColumnMappings) { ColumnMapping targetColumnMapping = new ColumnMapping { ColumnName = sourceColumnMapping.ColumnName, IsMapped = sourceColumnMapping.IsMapped, PropertyId = sourceColumnMapping.PropertyId, IsScalarProperty = sourceColumnMapping.IsScalarProperty }; targetTableMapping.ColumnMappings.Add(targetColumnMapping); } } return(newTableMappings); }
/// <summary> /// Updates the MSL. /// </summary> /// <param name="entityTypeMapping">The entity type mapping.</param> /// <param name="tableMappings">The table mappings.</param> /// <param name="discriminators">The discriminators.</param> internal void UpdateMsl(XmlElement entityTypeMapping, TableMappingCollection tableMappings, Dictionary <Guid, int> discriminators) { // Locate the table and column mappings for this property. ColumnMapping columnMapping = tableMappings.GetColumnMappingByPropertyId(this.Id); TableMapping tableMapping = columnMapping.Parent; string cachedTableName = tableMapping.TableName; string cachedColumnName = columnMapping.ColumnName; // Locate or create <MappingFragment> element. XmlNamespaceManager nsMgr = new XmlNamespaceManager( entityTypeMapping.OwnerDocument.NameTable); nsMgr.AddNamespace(DataModellingResources.MSLNamespacePrefix, DataModellingResources.MSLSchemaNamespace); XmlNodeList mappingFragments = entityTypeMapping.SelectNodes( string.Format(CultureInfo.InvariantCulture, DataModellingResources.XPathMSLMappingFragment, cachedTableName), nsMgr); XmlElement mappingFragment = null; if (mappingFragments.Count == 0) { mappingFragment = Utilities.CreateElement(entityTypeMapping, DataModellingResources.MappingFragment); Utilities.AddAttribute(mappingFragment, DataModellingResources.StoreEntitySet, cachedTableName); // Add mapping for the Id column. XmlElement idMapping = Utilities.CreateElement(mappingFragment, DataModellingResources.ScalarProperty); Utilities.AddAttribute(idMapping, DataModellingResources.Name, DataModellingResources.Id); Utilities.AddAttribute(idMapping, DataModellingResources.ColumnName, DataModellingResources.Id); // Add Condition element. XmlElement conditionElement = Utilities.CreateElement(mappingFragment, DataModellingResources.Condition); Utilities.AddAttribute(conditionElement, DataModellingResources.ColumnName, DataModellingResources.Discriminator); Utilities.AddAttribute(conditionElement, DataModellingResources.Value, discriminators[this.Parent.Id].ToString(CultureInfo.InvariantCulture). ToLowerInvariant()); } else { mappingFragment = mappingFragments[0] as XmlElement; } // Create <ScalarProperty> element. XmlElement scalarProperty = Utilities.CreateElement(mappingFragment, DataModellingResources.ScalarProperty); Utilities.AddAttribute(scalarProperty, DataModellingResources.Name, this.Name); Utilities.AddAttribute(scalarProperty, DataModellingResources.ColumnName, cachedColumnName); }
internal void UpdateSsdl(XmlDocument ssdlDocument, TableMappingCollection tableMappings) { // Process custom resource types. foreach (ResourceType resourceType in this.ResourceTypes) { resourceType.UpdateSsdl(ssdlDocument, tableMappings); } // Process custom associations. foreach (Association association in this.Associations) { association.UpdateSsdl(ssdlDocument, tableMappings); } }
internal void UpdateMsl(XmlDocument mslDocument, TableMappingCollection tableMappings, Dictionary <Guid, int> discriminators, string storageSchemaName) { // Sort the resource types. We copy over mapping fragments from base type to the // derived type and thus it is required that the base type is processed before // derived types. List <ResourceType> sortedTypes = DataModel.SortByHierarchy( this.ResourceTypes.ToList()); // Process Resource Types. foreach (ResourceType resourceType in sortedTypes) { resourceType.UpdateMsl(mslDocument, tableMappings, discriminators, storageSchemaName); } // Process Associations. foreach (Association association in this.Associations) { association.UpdateMsl(mslDocument, tableMappings, storageSchemaName); } }
/// <summary> /// Updates the SSDL. /// </summary> /// <param name="ssdlDocument">The SSDL document.</param> /// <param name="tableMappings">The table mappings.</param> internal void UpdateSsdl(XmlDocument ssdlDocument, TableMappingCollection tableMappings) { // Locate the table and column mappings for this property. ColumnMapping columnMapping = tableMappings.GetColumnMappingByPropertyId( this.Id); TableMapping tableMapping = columnMapping.Parent; string cachedTableName = tableMapping.TableName; string cachedColumnName = columnMapping.ColumnName; XmlNamespaceManager nsMgr = new XmlNamespaceManager(ssdlDocument.NameTable); nsMgr.AddNamespace(DataModellingResources.SSDLNamespacePrefix, DataModellingResources.SSDLSchemaNameSpace); // Locate the Schema element. XmlElement schemaElement = ssdlDocument.SelectSingleNode( DataModellingResources.XPathSSDLSchema, nsMgr) as XmlElement; string storageSchemaNamespace = schemaElement.Attributes[DataModellingResources.Namespace]. Value; string tableFullName = Utilities.MergeSubNames(storageSchemaNamespace, cachedTableName); // Locate the EntityType for this table. XmlElement entityContainerElement = ssdlDocument.SelectSingleNode( DataModellingResources.XPathSSDLEntityContainer, nsMgr) as XmlElement; XmlNodeList entityTypes = schemaElement.SelectNodes(string.Format( CultureInfo.InvariantCulture, DataModellingResources.XPathSSDLEntityType, cachedTableName), nsMgr); XmlElement entityTypeElement = null; // If not found, create the EntitySet and the EntityType elements. // NOTE: We have added and FK from new table to Resource table. This is necessary // so that EF inserts entries in the correct order across multiple tables. For // example, let's say EntityA spans across 3 tables, Resource, Tab1 and Tab2. The // entity has a one-to-many association with itself. The FK column resides in Tab2. // Now let's say we create just one resource and associate it with itself. While // entering the details for this resource, if EF inserts values into Tab2 before // Resource, the foreign key constraint might fail. if (entityTypes.Count == 0) { // Create EntitySet element. Utilities.AddSsdlEntitySetForTables(entityContainerElement, cachedTableName, tableFullName, DataModellingResources.Core); // Create AssociationSet element. string fkConstraintName = string.Format(CultureInfo.InvariantCulture, DataModellingResources.FKConstraintName, cachedTableName); string fkConstraintFullName = Utilities.MergeSubNames(storageSchemaNamespace, fkConstraintName); Utilities.AddSsdlAssociationSet(entityContainerElement, fkConstraintName, fkConstraintFullName, DataModellingResources.Resource, DataModellingResources.Resource, cachedTableName, cachedTableName); // Create EntityType element entityTypeElement = Utilities.AddSsdlEntityType(schemaElement, cachedTableName, DataModellingResources.Id); // Add Id and Discriminator properties. Utilities.AddSsdlEntityTypeProperty(entityTypeElement, DataModellingResources.Id, DataModellingResources.DataTypeUniqueidentifier, false); Utilities.AddSsdlEntityTypeProperty(entityTypeElement, DataModellingResources.Discriminator, DataModellingResources.DataTypeInt, false); // Create Association element. Utilities.AddSsdlAssociation(schemaElement, fkConstraintName, DataModellingResources.Resource, Utilities.MergeSubNames(storageSchemaNamespace, DataModellingResources.Resource), DataModellingResources.One, cachedTableName, Utilities.MergeSubNames(storageSchemaNamespace, cachedTableName), DataModellingResources.ZeroOrOne, DataModellingResources.Resource, new string[] { DataModellingResources.Id }, cachedTableName, new string[] { DataModellingResources.Id }); } else { entityTypeElement = entityTypes[0] as XmlElement; } // Add Name, ManagerType, Nullable and data type specific attributes. // NOTE: Nullable is always true in the SSDL. This is important for the TPH // type of mapping. if (this.DataType == DataTypes.String || this.DataType == DataTypes.Binary) { if (this.MaxLength < 0) { Utilities.AddSsdlEntityTypeProperty(entityTypeElement, cachedColumnName, Utilities.GetSQLType(this.DataType) + string.Format(CultureInfo.InvariantCulture, DataModellingResources.Paranthesis, DataModellingResources.Max).ToLowerInvariant(), true); } else { Utilities.AddSsdlEntityTypeProperty(entityTypeElement, cachedColumnName, Utilities.GetSQLType(this.DataType), true, this.MaxLength); } } else if (this.DataType == DataTypes.Decimal) { Utilities.AddSsdlEntityTypeProperty(entityTypeElement, cachedColumnName, Utilities.GetSQLType(this.DataType), true, this.Precision, this.Scale); } else { Utilities.AddSsdlEntityTypeProperty(entityTypeElement, cachedColumnName, Utilities.GetSQLType(this.DataType), true); } }
internal void UpdateMsl(XmlDocument mslDocument, TableMappingCollection tableMappings, Dictionary <Guid, int> discriminators, string storageSchemaName) { // Locate the <EntitySetMapping Name="Resources"> element XmlNamespaceManager nsMgr = new XmlNamespaceManager(mslDocument.NameTable); nsMgr.AddNamespace(CoreResources.MSLNamespacePrefix, CoreResources.MSLSchemaNamespace); XmlElement entityContainerMappingElement = mslDocument.SelectSingleNode( CoreResources.XPathMSLEntityContainerMapping, nsMgr) as XmlElement; XmlElement entitySetMappingElement = mslDocument.SelectSingleNode( string.Format(CultureInfo.InvariantCulture, CoreResources.XPathMSLEntitySetMapping, CoreResources.Resources), nsMgr) as XmlElement; // Create <EntityTypeMapping> element. XmlElement entityTypeMapping = Utilities.CreateElement(entitySetMappingElement, CoreResources.EntityTypeMapping); Utilities.AddAttribute(entityTypeMapping, CoreResources.TypeName, this.FullName); // Copy over the mapping fragments from base type. XmlElement baseEntityTypeMapping = entitySetMappingElement.SelectSingleNode( string.Format(CultureInfo.InvariantCulture, CoreResources.XPathMSLEntityTypeMapping, this.BaseType.FullName), nsMgr) as XmlElement; foreach (XmlNode xMappingFragment in baseEntityTypeMapping.SelectNodes( CoreResources.XPathMSLRelativeMappingFragments, nsMgr)) { XmlNode derivedMappingFragment = entityTypeMapping.AppendChild( mslDocument.ImportNode(xMappingFragment, true)); XmlElement conditionElement = derivedMappingFragment[CoreResources.Condition]; conditionElement.Attributes[CoreResources.Value].Value = discriminators[this.Id]. ToString(CultureInfo.InvariantCulture).ToLowerInvariant(); } // Process scalar properties. foreach (ScalarProperty scalarProperty in this.ScalarProperties) { scalarProperty.UpdateMsl(entityTypeMapping, tableMappings, discriminators); } #region Create ModificationFunctionMapping element. // Create Function Import Mappings. string insertFunctionFullName = Utilities.MergeSubNames(storageSchemaName, InsertProcedureName); string updateFunctionFullName = Utilities.MergeSubNames(storageSchemaName, UpdateProcedureName); string deleteFunctionFullName = Utilities.MergeSubNames(storageSchemaName, DeleteProcedureName); Utilities.AddMslFunctionImportMapping(entityContainerMappingElement, InsertProcedureName, insertFunctionFullName); Utilities.AddMslFunctionImportMapping(entityContainerMappingElement, UpdateProcedureName, updateFunctionFullName); Utilities.AddMslFunctionImportMapping(entityContainerMappingElement, DeleteProcedureName, deleteFunctionFullName); XmlElement modificationFunctionMappingElement = Utilities.CreateElement( entityTypeMapping, CoreResources.ModificationFunctionMapping); XmlElement insertFunctionElement = Utilities.CreateElement( modificationFunctionMappingElement, CoreResources.InsertFunction); Utilities.AddAttribute(insertFunctionElement, CoreResources.FunctionName, insertFunctionFullName); XmlElement updateFunctionElement = Utilities.CreateElement( modificationFunctionMappingElement, CoreResources.UpdateFunction); Utilities.AddAttribute(updateFunctionElement, CoreResources.FunctionName, updateFunctionFullName); XmlElement deleteFunctionElement = Utilities.CreateElement( modificationFunctionMappingElement, CoreResources.DeleteFunction); Utilities.AddAttribute(deleteFunctionElement, CoreResources.FunctionName, deleteFunctionFullName); // DeleteFunction always has an Id scalar property mapping. { XmlElement scalarPropertyElement = Utilities.CreateElement( deleteFunctionElement, CoreResources.ScalarProperty); Utilities.AddAttribute(scalarPropertyElement, CoreResources.Name, CoreResources.Id); Utilities.AddAttribute(scalarPropertyElement, CoreResources.ParameterName, CoreResources.Id); } ResourceType tempType = this; while (tempType != null) { foreach (ScalarProperty scalarProperty in tempType.ScalarProperties) { XmlElement scalarPropertyElement = Utilities.CreateElement( insertFunctionElement, CoreResources.ScalarProperty); Utilities.AddAttribute(scalarPropertyElement, CoreResources.Name, scalarProperty.Name); Utilities.AddAttribute(scalarPropertyElement, CoreResources.ParameterName, scalarProperty.Name); // Only UpdateFunction has the Version attribute = "Current". scalarPropertyElement = updateFunctionElement.AppendChild( mslDocument.ImportNode(scalarPropertyElement, true)) as XmlElement; Utilities.AddAttribute(scalarPropertyElement, CoreResources.Version, CoreResources.Current); } foreach (NavigationProperty navigationProperty in tempType.NavigationProperties) { Association association = navigationProperty.Association; // Assumption here is that there are no One-To-One associations in the data model. if (navigationProperty.Direction == AssociationEndType.Subject && association.ObjectMultiplicity == AssociationEndMultiplicity.One || navigationProperty.Direction == AssociationEndType.Object && association.SubjectMultiplicity == AssociationEndMultiplicity.One) { XmlElement associationEndElement = Utilities.CreateElement(insertFunctionElement, CoreResources.AssociationEnd); Utilities.AddAttribute(associationEndElement, CoreResources.AssociationSet, association.Name); if (navigationProperty.Direction == AssociationEndType.Subject) { Utilities.AddAttribute(associationEndElement, CoreResources.From, association.SubjectRole); Utilities.AddAttribute(associationEndElement, CoreResources.To, association.ObjectRole); } else { Utilities.AddAttribute(associationEndElement, CoreResources.From, association.ObjectRole); Utilities.AddAttribute(associationEndElement, CoreResources.To, association.SubjectRole); } XmlElement scalarPropertyElement = Utilities.CreateElement(associationEndElement, CoreResources.ScalarProperty); Utilities.AddAttribute(scalarPropertyElement, CoreResources.Name, CoreResources.Id); Utilities.AddAttribute(scalarPropertyElement, CoreResources.ParameterName, navigationProperty.Name); deleteFunctionElement.AppendChild(mslDocument.ImportNode(associationEndElement, true)); // Only UpdateFunction has the Version attribute = "Current". associationEndElement = updateFunctionElement.AppendChild( mslDocument.ImportNode(associationEndElement, true)) as XmlElement; scalarPropertyElement = associationEndElement[CoreResources.ScalarProperty]; Utilities.AddAttribute(scalarPropertyElement, CoreResources.Version, CoreResources.Current); } } tempType = tempType.BaseType; } #endregion }
private static void UpdateSsdlHandleOneToXxxAssociations(XmlElement entityContainerElement, XmlElement schemaElement, Guid xxxSidePropertyId, TableMappingCollection tableMappings) { // Locate the table and column mappings for this property. ColumnMapping columnMapping = tableMappings.GetColumnMappingByPropertyId( xxxSidePropertyId); TableMapping tableMapping = columnMapping.Parent; string tableName = tableMapping.TableName; string columnName = columnMapping.ColumnName; string storageSchemaNamespace = schemaElement.Attributes[CoreResources.Namespace]. Value; string tableFullName = Utilities.MergeSubNames( storageSchemaNamespace, tableName); // Locate the EntityType for this table. XmlNamespaceManager nsMgr = new XmlNamespaceManager( entityContainerElement.OwnerDocument.NameTable); nsMgr.AddNamespace(CoreResources.SSDLNamespacePrefix, CoreResources.SSDLSchemaNameSpace); XmlNodeList entityTypes = schemaElement.SelectNodes(string.Format( CultureInfo.InvariantCulture, CoreResources.XPathSSDLEntityType, tableName), nsMgr); XmlElement entityTypeElement = null; // If not found, create the EntitySet and the EntityType elements. // NOTE: We have added and FK from new table to Resource table. This is necessary // so that EF inserts entries in the correct order across multiple tables. For // example, let's say EntityA spans across 3 tables, Resource, Tab1 and Tab2. The // entity has a one-to-many association with itself. The FK column resides in Tab2. // Now let's say we create just one resource and associate it with itself. While // entering the details for this resource, if EF inserts values into Tab2 before // Resource, the foreign key constraint might fail. if (entityTypes.Count == 0) { // Create EntitySet element. Utilities.AddSsdlEntitySetForTables(entityContainerElement, tableName, tableFullName, CoreResources.Core); // Create AssociationSet element. string fkConstraintName = string.Format(CultureInfo.InvariantCulture, CoreResources.FKConstraintName, tableName); string fkConstraintFullName = Utilities.MergeSubNames( storageSchemaNamespace, fkConstraintName); Utilities.AddSsdlAssociationSet(entityContainerElement, fkConstraintName, fkConstraintFullName, CoreResources.Resource, CoreResources.Resource, tableName, tableName); // Create EntityType element entityTypeElement = Utilities.AddSsdlEntityType(schemaElement, tableName, CoreResources.Id); // Add Id and Discriminator properties. Utilities.AddSsdlEntityTypeProperty(entityTypeElement, CoreResources.Id, CoreResources.DataTypeUniqueidentifier, false); Utilities.AddSsdlEntityTypeProperty(entityTypeElement, CoreResources.Discriminator, CoreResources.DataTypeInt, false); // Create Association element. Utilities.AddSsdlAssociation(schemaElement, fkConstraintName, CoreResources.Resource, Utilities.MergeSubNames( storageSchemaNamespace, CoreResources.Resource), CoreResources.One, tableName, tableFullName, CoreResources.ZeroOrOne, CoreResources.Resource, new string[] { CoreResources.Id }, tableName, new string[] { CoreResources.Id }); } else { entityTypeElement = entityTypes[0] as XmlElement; } // Add the foreign key column to EntityType element. Take note that all // foreign key columns are nullable. This is necessary since the table // might also host rows for some other entity type and while inserting // rows for the other entity type, EF inserts NULL values for this entity // type. Utilities.AddSsdlEntityTypeProperty(entityTypeElement, columnName, CoreResources.DataTypeUniqueidentifier, true); // Add AssociationSet element for the foreign key. It is possible that the FK // column is hosted by Resource table. To create different roles, we use the // column name to distinguish between the roles. string associationFKConstraintName = string.Format(CultureInfo.InvariantCulture, CoreResources.FKConstraintName, columnName); string associationFKConstraintFullName = Utilities.MergeSubNames( storageSchemaNamespace, associationFKConstraintName); Utilities.AddSsdlAssociationSet(entityContainerElement, associationFKConstraintName, associationFKConstraintFullName, CoreResources.Resource, CoreResources.Resource, columnName, tableName); // Add Association element. Utilities.AddSsdlAssociation(schemaElement, associationFKConstraintName, CoreResources.Resource, Utilities.MergeSubNames( storageSchemaNamespace, CoreResources.Resource), CoreResources.ZeroOrOne, columnName, tableFullName, CoreResources.Many, CoreResources.Resource, new string[] { CoreResources.Id }, columnName, new string[] { columnName }); }
internal void UpdateMsl(XmlDocument mslDocument, TableMappingCollection tableMappings, string storageSchemaName) { // Locate the EntityContainer element. XmlNamespaceManager nsMgr = new XmlNamespaceManager(mslDocument.NameTable); nsMgr.AddNamespace(CoreResources.MSLNamespacePrefix, CoreResources.MSLSchemaNamespace); XmlElement entityContainerMappingElement = mslDocument.SelectSingleNode( CoreResources.XPathMSLEntityContainerMapping, nsMgr) as XmlElement; // We don't support One to One associations. if (this.SubjectMultiplicity == AssociationEndMultiplicity.One && this.ObjectMultiplicity == AssociationEndMultiplicity.One) { throw new ZentityException(CoreResources.InvalidMultiplicityOneToOne); } // Handle view mappings. else if (this.SubjectMultiplicity == AssociationEndMultiplicity.Many && this.ObjectMultiplicity == AssociationEndMultiplicity.Many || this.SubjectMultiplicity == AssociationEndMultiplicity.Many && this.ObjectMultiplicity == AssociationEndMultiplicity.ZeroOrOne || this.SubjectMultiplicity == AssociationEndMultiplicity.ZeroOrOne && this.ObjectMultiplicity == AssociationEndMultiplicity.Many || this.SubjectMultiplicity == AssociationEndMultiplicity.ZeroOrOne && this.ObjectMultiplicity == AssociationEndMultiplicity.ZeroOrOne) { // Create FunctionImportMapping elements. string createFunctionFullName = Utilities.MergeSubNames( storageSchemaName, InsertProcedureName); string deleteFunctionFullName = Utilities.MergeSubNames( storageSchemaName, DeleteProcedureName); Utilities.AddMslFunctionImportMapping(entityContainerMappingElement, InsertProcedureName, createFunctionFullName); Utilities.AddMslFunctionImportMapping(entityContainerMappingElement, DeleteProcedureName, deleteFunctionFullName); // Create AssociationSetMapping element. UpdateMslCreateAssociationSetMappingElement(entityContainerMappingElement, this.Name, this.FullName, this.ViewName, this.SubjectRole, CoreResources.Id, CoreResources.SubjectResourceId, this.ObjectRole, CoreResources.Id, CoreResources.ObjectResourceId, createFunctionFullName, deleteFunctionFullName, CoreResources.SubjectResourceId, CoreResources.ObjectResourceId); } else { ColumnMapping columnMapping = null; XmlElement associationSetMappingElement = null; // Handle OneToXXX mappings except One to One. if (this.SubjectMultiplicity == AssociationEndMultiplicity.One) { columnMapping = tableMappings.GetColumnMappingByPropertyId( this.ObjectNavigationProperty.Id); associationSetMappingElement = UpdateMslCreateAssociationSetMappingElement( entityContainerMappingElement, this.Name, this.FullName, columnMapping.Parent.TableName, this.SubjectRole, CoreResources.Id, columnMapping.ColumnName, this.ObjectRole, CoreResources.Id, CoreResources.Id); } // Handle XXXToOne mappings except One to One. else { columnMapping = tableMappings.GetColumnMappingByPropertyId( this.SubjectNavigationProperty.Id); associationSetMappingElement = UpdateMslCreateAssociationSetMappingElement( entityContainerMappingElement, this.Name, this.FullName, columnMapping.Parent.TableName, this.SubjectRole, CoreResources.Id, CoreResources.Id, this.ObjectRole, CoreResources.Id, columnMapping.ColumnName); } // Add the NOT NULL Condition element for foreign key column. XmlElement conditionElement = Utilities.CreateElement(associationSetMappingElement, CoreResources.Condition); Utilities.AddAttribute(conditionElement, CoreResources.ColumnName, columnMapping.ColumnName); Utilities.AddAttribute(conditionElement, CoreResources.IsNull, false.ToString().ToLowerInvariant()); } }
internal void UpdateSsdl(XmlDocument ssdlDocument, TableMappingCollection tableMappings) { // Pick the Schema and EntityContainer elements. XmlNamespaceManager nsMgr = new XmlNamespaceManager(ssdlDocument.NameTable); nsMgr.AddNamespace(CoreResources.SSDLNamespacePrefix, CoreResources.SSDLSchemaNameSpace); XmlElement schemaElement = ssdlDocument.SelectSingleNode( CoreResources.XPathSSDLSchema, nsMgr) as XmlElement; XmlElement entityContainerElement = ssdlDocument.SelectSingleNode( CoreResources.XPathSSDLEntityContainer, nsMgr) as XmlElement; // Parameters for View associations // (ManyToMany, ManyToZeroOrOne, ZeroOrOneToMany, ZeroOrOneToZeroOrOne). string viewName = this.ViewName; string subjectFKConstraintName = string.Format(CultureInfo.InvariantCulture, CoreResources.FKConstraintName, this.SubjectNavigationProperty.Id.ToString()); string objectFKConstraintName = string.Format(CultureInfo.InvariantCulture, CoreResources.FKConstraintName, this.ObjectNavigationProperty.Id.ToString()); // One to One. if (this.SubjectMultiplicity == AssociationEndMultiplicity.One && this.ObjectMultiplicity == AssociationEndMultiplicity.One) { throw new ZentityException(CoreResources.InvalidMultiplicityOneToOne); } // Many to Many. if (this.SubjectMultiplicity == AssociationEndMultiplicity.Many && this.ObjectMultiplicity == AssociationEndMultiplicity.Many) { UpdateSsdlHandleViewAssociations(entityContainerElement, schemaElement, viewName, subjectFKConstraintName, objectFKConstraintName, new string[] { CoreResources.SubjectResourceId, CoreResources.ObjectResourceId }, CoreResources.One, CoreResources.Many, CoreResources.One, CoreResources.Many, InsertProcedureName, DeleteProcedureName); } // Many to One or ZeroOrOne to One. if (this.SubjectMultiplicity == AssociationEndMultiplicity.Many && this.ObjectMultiplicity == AssociationEndMultiplicity.One || this.SubjectMultiplicity == AssociationEndMultiplicity.ZeroOrOne && this.ObjectMultiplicity == AssociationEndMultiplicity.One) { UpdateSsdlHandleOneToXxxAssociations(entityContainerElement, schemaElement, this.SubjectNavigationProperty.Id, tableMappings); } // Many to ZeroOrOne OR ZeroOrOne to ZeroOrOne. if (this.SubjectMultiplicity == AssociationEndMultiplicity.Many && this.ObjectMultiplicity == AssociationEndMultiplicity.ZeroOrOne || this.SubjectMultiplicity == AssociationEndMultiplicity.ZeroOrOne && this.ObjectMultiplicity == AssociationEndMultiplicity.ZeroOrOne) { UpdateSsdlHandleViewAssociations(entityContainerElement, schemaElement, viewName, subjectFKConstraintName, objectFKConstraintName, new string[] { CoreResources.SubjectResourceId }, CoreResources.One, CoreResources.ZeroOrOne, CoreResources.One, CoreResources.Many, InsertProcedureName, DeleteProcedureName); } // One to Many or One to ZeroOrOne. if (this.SubjectMultiplicity == AssociationEndMultiplicity.One && this.ObjectMultiplicity == AssociationEndMultiplicity.Many || this.SubjectMultiplicity == AssociationEndMultiplicity.One && this.ObjectMultiplicity == AssociationEndMultiplicity.ZeroOrOne) { UpdateSsdlHandleOneToXxxAssociations(entityContainerElement, schemaElement, this.ObjectNavigationProperty.Id, tableMappings); } // ZeroOrOne to Many. if (this.SubjectMultiplicity == AssociationEndMultiplicity.ZeroOrOne && this.ObjectMultiplicity == AssociationEndMultiplicity.Many) { UpdateSsdlHandleViewAssociations(entityContainerElement, schemaElement, viewName, subjectFKConstraintName, objectFKConstraintName, new string[] { CoreResources.ObjectResourceId }, CoreResources.One, CoreResources.Many, CoreResources.One, CoreResources.ZeroOrOne, InsertProcedureName, DeleteProcedureName); } }