Beispiel #1
0
        internal static XElement ConstructReferentialConstraint(
            string principalRole, AssociationEndMember principalEnd,
            string dependentRole, AssociationEndMember dependentEnd)
        {
            var refConstraintElement = new XElement(_ssdl + "ReferentialConstraint");

            if (dependentEnd != null &&
                principalEnd != null)
            {
                var dependentEntityType = dependentEnd.GetEntityType();
                var principalEntityType = principalEnd.GetEntityType();
                if (dependentEntityType != null &&
                    principalEntityType != null)
                {
                    refConstraintElement = ConstructReferentialConstraintInternal(
                        principalRole,
                        principalEntityType.GetKeyProperties().Select(k => k.Name),
                        dependentRole,
                        principalEntityType.GetKeyProperties().Select(
                            k => OutputGeneratorHelpers.GetFkName(
                                dependentEnd.DeclaringType as AssociationType,
                                dependentEnd,
                                k.Name)));
                }
            }

            return(refConstraintElement);
        }
Beispiel #2
0
        internal static List <XElement> ConstructEntityTypes(
            EdmItemCollection edmItemCollection, DbProviderManifest providerManifest, Version targetVersion)
        {
            var entityTypes = new List <XElement>();

            // Translate the CSDL EntityTypes into SSDL EntityTypes
            foreach (var csdlEntityType in edmItemCollection.GetAllEntityTypes())
            {
                var entityTypeElement =
                    new XElement(
                        _ssdl + "EntityType",
                        new XAttribute("Name", OutputGeneratorHelpers.GetStorageEntityTypeName(csdlEntityType, edmItemCollection)));

                // Add the keys
                if (csdlEntityType.GetRootOrSelf().GetKeyProperties().Any())
                {
                    var keyElement = new XElement(_ssdl + "Key");
                    foreach (EdmMember key in csdlEntityType.GetRootOrSelf().GetKeyProperties())
                    {
                        keyElement.Add(new XElement(_ssdl + "PropertyRef", new XAttribute("Name", key.Name)));
                    }
                    entityTypeElement.Add(keyElement);
                }

                // Add only the properties on the declared type but also add the keys that might be on the root type
                foreach (
                    var property in
                    csdlEntityType.Properties.Where(p => (p.DeclaringType == csdlEntityType))
                    .Union(csdlEntityType.GetRootOrSelf().GetKeyProperties()))
                {
                    // If we encounter a ComplexType, we need to recursively flatten it out
                    // into a list of all contained properties
                    if (property.IsComplexProperty())
                    {
                        property.VisitComplexProperty(
                            (namePrefix, nestedProperty) =>
                        {
                            var propertyElement = new XElement(
                                _ssdl + "Property",
                                new XAttribute("Name", namePrefix),
                                new XAttribute("Type", nestedProperty.GetStoreType(providerManifest)));

                            // Add StoreGeneratedPattern if it exists, but only add this to the table created from
                            // the root type
                            if (property.DeclaringType == csdlEntityType)
                            {
                                propertyElement.Add(ConstructStoreGeneratedPatternAttribute(nestedProperty, targetVersion));
                            }

                            // Add the facets
                            foreach (var facet in nestedProperty.InferSsdlFacetsForCsdlProperty(providerManifest))
                            {
                                if (facet.Value != null)
                                {
                                    propertyElement.Add(new XAttribute(facet.Name, facet.Value));
                                }
                            }

                            // We'll identify extended properties on all nested properties and migrate them.
                            OutputGeneratorHelpers.CopyExtendedPropertiesToSsdlElement(nestedProperty, propertyElement);

                            entityTypeElement.Add(propertyElement);
                        }, "_", true);
                    }
                    else
                    {
                        var propertyElement = new XElement(
                            _ssdl + "Property",
                            new XAttribute("Name", property.Name),
                            new XAttribute("Type", property.GetStoreType(providerManifest)));

                        // Add StoreGeneratedPattern if it exists, but only add this to the table created from
                        // the root type
                        if (property.DeclaringType == csdlEntityType)
                        {
                            propertyElement.Add(ConstructStoreGeneratedPatternAttribute(property, targetVersion));
                        }

                        // Add the facets
                        foreach (var facet in property.InferSsdlFacetsForCsdlProperty(providerManifest))
                        {
                            if (facet.Value != null)
                            {
                                var facetValue = facet.Value;

                                // for DateTime attributes, if allow XAttribute to use its default formatting we end up
                                // with attribute such as:
                                // Facet="yyyy-MM-ddTHH:mm:ssZ", but we need Facet="yyyy-MM-dd HH:mm:ss.fffZ" (note the
                                // space instead of 'T' and the fractions of seconds) to be valid SSDL
                                if (typeof(DateTime).Equals(facetValue.GetType()))
                                {
                                    facetValue = string.Format(
                                        CultureInfo.InvariantCulture, "{0:yyyy'-'MM'-'dd HH':'mm':'ss'.'fff'Z'}", facet.Value);
                                }
                                propertyElement.Add(new XAttribute(facet.Name, facetValue));
                            }
                        }

                        OutputGeneratorHelpers.CopyExtendedPropertiesToSsdlElement(property, propertyElement);

                        entityTypeElement.Add(propertyElement);
                    }
                }

                // 1. If there is a Referential Constraint specified on the C-side then there is no need
                //      to create foreign keys since the dependent end's primary keys are the foreign keys.
                // 2. In other cases, we will have to infer the foreign keys by examining any associations that
                //      the entity type participates in and add the principal keys as the foreign keys on the
                //      dependent end.
                foreach (var containedAssociation in edmItemCollection.GetAllAssociations()
                         .Where(
                             a => (a.IsManyToMany() == false) &&
                             (a.ReferentialConstraints.Count == 0) &&
                             (a.GetDependentEnd().GetEntityType() == csdlEntityType)))
                {
                    foreach (var keyProperty in containedAssociation.GetPrincipalEnd().GetEntityType().GetKeyProperties())
                    {
                        var propertyElement = new XElement(
                            _ssdl + "Property",
                            new XAttribute(
                                "Name",
                                OutputGeneratorHelpers.GetFkName(
                                    containedAssociation, containedAssociation.GetDependentEnd(), keyProperty.Name)),
                            new XAttribute("Type", keyProperty.GetStoreType(providerManifest)));

                        // Add the facets
                        foreach (var facet in keyProperty.InferSsdlFacetsForCsdlProperty(providerManifest))
                        {
                            if (facet.Value != null &&
                                !facet.Name.Equals("Nullable", StringComparison.OrdinalIgnoreCase))
                            {
                                propertyElement.Add(new XAttribute(facet.Name, facet.Value));
                            }
                        }

                        // The Nullability of this property is dependent on the multiplicity of the association.
                        // If the principal end's multiplicity is 0..1, then this property is Nullable.
                        propertyElement.Add(
                            new XAttribute(
                                "Nullable",
                                containedAssociation.GetPrincipalEnd().RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne));

                        entityTypeElement.Add(propertyElement);
                    }
                }

                OutputGeneratorHelpers.CopyExtendedPropertiesToSsdlElement(csdlEntityType, entityTypeElement);

                entityTypes.Add(entityTypeElement);
            }

            // For all *:* Associations, we need a pair table and an associated pair EntityType
            foreach (var assoc in edmItemCollection.GetItems <AssociationType>().Where(a => a.IsManyToMany()))
            {
                var entityTypeElement = new XElement(_ssdl + "EntityType", new XAttribute("Name", assoc.Name));

                // We determine the properties as the aggregation of the primary keys from both ends of the association.
                // These properties are also the keys of this new EntityTyp
                var keyElement = new XElement(_ssdl + "Key");
                foreach (var key in assoc.GetEnd1().GetKeyProperties())
                {
                    keyElement.Add(
                        new XElement(
                            _ssdl + "PropertyRef",
                            new XAttribute("Name", OutputGeneratorHelpers.GetFkName(assoc, assoc.GetEnd2(), key.Name))));
                }
                foreach (var key in assoc.GetEnd2().GetKeyProperties())
                {
                    keyElement.Add(
                        new XElement(
                            _ssdl + "PropertyRef",
                            new XAttribute("Name", OutputGeneratorHelpers.GetFkName(assoc, assoc.GetEnd1(), key.Name))));
                }
                entityTypeElement.Add(keyElement);

                // These are foreign keys as well; we create 0..1 associations so these will be nullable keys
                foreach (var property in assoc.GetEnd1().GetKeyProperties())
                {
                    var propertyElement = new XElement(
                        _ssdl + "Property",
                        new XAttribute("Name", OutputGeneratorHelpers.GetFkName(assoc, assoc.GetEnd2(), property.Name)),
                        new XAttribute("Type", property.GetStoreType(providerManifest)));

                    // Add the facets
                    foreach (var facet in property.InferSsdlFacetsForCsdlProperty(providerManifest))
                    {
                        if (facet.Value != null)
                        {
                            propertyElement.Add(new XAttribute(facet.Name, facet.Value));
                        }
                    }

                    entityTypeElement.Add(propertyElement);
                }
                foreach (var property in assoc.GetEnd2().GetKeyProperties())
                {
                    var propertyElement = new XElement(
                        _ssdl + "Property",
                        new XAttribute("Name", OutputGeneratorHelpers.GetFkName(assoc, assoc.GetEnd1(), property.Name)),
                        new XAttribute("Type", property.GetStoreType(providerManifest)));

                    // Add the facets
                    foreach (var facet in property.InferSsdlFacetsForCsdlProperty(providerManifest))
                    {
                        if (facet.Value != null)
                        {
                            propertyElement.Add(new XAttribute(facet.Name, facet.Value));
                        }
                    }

                    entityTypeElement.Add(propertyElement);
                }

                entityTypes.Add(entityTypeElement);
            }

            return(entityTypes);
        }
        internal static List <XElement> ConstructAssociationSetMappings(
            EdmItemCollection edm, string csdlNamespace, Version targetFrameworkVersion)
        {
            string prefix = OutputGeneratorHelpers.GetTablePrefix(edm.GetNamespace());
            var    associationSetMappings = new List <XElement>();

            foreach (var associationSet in edm.GetAllAssociationSets())
            {
                var association = associationSet.ElementType;

                if (association.IsManyToMany())
                {
                    var entityType1 = association.GetEnd1().GetEntityType();
                    var entityType2 = association.GetEnd2().GetEntityType();

                    var associationSetMapping = new XElement(
                        _msl + "AssociationSetMapping",
                        new XAttribute("Name", associationSet.Name),
                        new XAttribute("TypeName", csdlNamespace + "." + associationSet.ElementType.Name),
                        new XAttribute("StoreEntitySet", prefix + associationSet.Name));
                    var end1Property = new XElement(_msl + "EndProperty", new XAttribute("Name", association.GetEnd1().Name));
                    foreach (var property in entityType1.GetKeyProperties())
                    {
                        end1Property.Add(
                            new XElement(
                                _msl + "ScalarProperty", new XAttribute("Name", property.Name),
                                new XAttribute(
                                    "ColumnName", OutputGeneratorHelpers.GetFkNameM2M(association, association.GetEnd2(), property.Name))));
                    }
                    associationSetMapping.Add(end1Property);
                    var end2Property = new XElement(_msl + "EndProperty", new XAttribute("Name", association.GetEnd2().Name));
                    foreach (var property in entityType2.GetKeyProperties())
                    {
                        end2Property.Add(
                            new XElement(
                                _msl + "ScalarProperty", new XAttribute("Name", property.Name),
                                new XAttribute(
                                    "ColumnName", OutputGeneratorHelpers.GetFkNameM2M(association, association.GetEnd1(), property.Name))));
                    }
                    associationSetMapping.Add(end2Property);
                    associationSetMappings.Add(associationSetMapping);
                }
                else
                {
                    if (targetFrameworkVersion == EntityFrameworkVersion.Version1 ||
                        association.ReferentialConstraints.Count <= 0)
                    {
                        var dependentEnd = association.GetDependentEnd();
                        var principalEnd = association.GetOtherEnd(dependentEnd);
                        if (dependentEnd != null &&
                            principalEnd != null)
                        {
                            var dependentEntityType   = dependentEnd.GetEntityType();
                            var principalEntityType   = principalEnd.GetEntityType();
                            var associationSetMapping = new XElement(
                                _msl + "AssociationSetMapping",
                                new XAttribute("Name", associationSet.Name),
                                new XAttribute("TypeName", csdlNamespace + "." + associationSet.ElementType.Name),
                                new XAttribute("StoreEntitySet", OutputGeneratorHelpers.GetStorageEntityTypeName(dependentEntityType, edm)));
                            var end1Property = new XElement(_msl + "EndProperty", new XAttribute("Name", principalEnd.Name));
                            foreach (var property in principalEntityType.GetKeyProperties())
                            {
                                var columnName = (association.ReferentialConstraints.Count > 0)
                                                     ? property.GetDependentProperty(association.ReferentialConstraints.FirstOrDefault())
                                                 .Name
                                                     : OutputGeneratorHelpers.GetFkName(association, dependentEnd, property.Name);
                                end1Property.Add(
                                    new XElement(
                                        _msl + "ScalarProperty", new XAttribute("Name", property.Name),
                                        new XAttribute("ColumnName", columnName)));
                            }
                            associationSetMapping.Add(end1Property);
                            var end2Property = new XElement(_msl + "EndProperty", new XAttribute("Name", dependentEnd.Name));
                            foreach (var property in dependentEntityType.GetKeyProperties())
                            {
                                end2Property.Add(
                                    new XElement(
                                        _msl + "ScalarProperty", new XAttribute("Name", property.Name),
                                        new XAttribute("ColumnName", property.Name)));
                            }
                            associationSetMapping.Add(end2Property);

                            // All 0..1 ends of a non PK:PK association require an IsNull=false condition
                            if (dependentEnd.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne
                                &&
                                !association.IsPKToPK())
                            {
                                foreach (var key in dependentEntityType.GetKeyProperties())
                                {
                                    associationSetMapping.Add(
                                        new XElement(
                                            _msl + "Condition", new XAttribute("ColumnName", key.Name), new XAttribute("IsNull", "false")));
                                }
                            }

                            if (principalEnd.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne)
                            {
                                foreach (var key in principalEntityType.GetKeyProperties())
                                {
                                    associationSetMapping.Add(
                                        new XElement(
                                            _msl + "Condition",
                                            new XAttribute(
                                                "ColumnName", OutputGeneratorHelpers.GetFkName(association, dependentEnd, key.Name)),
                                            new XAttribute("IsNull", "false")));
                                }
                            }
                            associationSetMappings.Add(associationSetMapping);
                        }
                    }
                }
            }
            return(associationSetMappings);
        }