예제 #1
0
        /// <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);
                }
            }
        }
예제 #2
0
        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
        }
예제 #3
0
        /// <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);
                }
            }
        }
예제 #4
0
        /// <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);
        }
예제 #5
0
        /// <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);
        }
예제 #6
0
        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);
            }
        }
예제 #7
0
        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);
            }
        }
예제 #8
0
        /// <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);
            }
        }
예제 #9
0
        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
        }
예제 #10
0
        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 });
        }
예제 #11
0
        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());
            }
        }
예제 #12
0
        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);
            }
        }