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 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); }
/// <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 }); }
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()); } }