/// <summary> /// Initializes a new instance of the <see cref="ColumnMappingCollection"/> class. /// </summary> /// <param name="parent">The parent.</param> internal ColumnMappingCollection(TableMapping parent) { this.parent = parent; this.innerMappings = new Collection <ColumnMapping>(); }
/// <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); } }
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 }); }