internal static XElement ConstructReferentialConstraint( string principalRole, AssociationEndMember principalEnd, string dependentRole, AssociationEndMember dependentEnd, bool M2M = false) { 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 => M2M ? OutputGeneratorHelpers.GetFkNameM2M( dependentEnd.DeclaringType as AssociationType, dependentEnd, k.Name) : OutputGeneratorHelpers.GetFkName( dependentEnd.DeclaringType as AssociationType, dependentEnd, k.Name))); } } return(refConstraintElement); }
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); }
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", OutputGeneratorHelpers.GetTablePrefix(assoc.NamespaceName) + 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.GetFkNameM2M(assoc, assoc.GetEnd2(), key.Name)))); } foreach (var key in assoc.GetEnd2().GetKeyProperties()) { keyElement.Add( new XElement( _ssdl + "PropertyRef", new XAttribute("Name", OutputGeneratorHelpers.GetFkNameM2M(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.GetFkNameM2M(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.GetFkNameM2M(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); }