public void ToLegacyEdmTypeUsage_returns_legacy_type_for_RowType() { const string csdl = "<Schema Namespace='AdventureWorksModel' Alias='Self' p1:UseStrongSpatialTypes='false' xmlns:annotation='http://schemas.microsoft.com/ado/2009/02/edm/annotation' xmlns:p1='http://schemas.microsoft.com/ado/2009/02/edm/annotation' xmlns='http://schemas.microsoft.com/ado/2009/11/edm'>" + " <Function Name='LastNamesAfter'>" + " <Parameter Name='someString' Type='Edm.String' />" + " <ReturnType>" + " <RowType>" + " <Property Name='FirstName' Type='Edm.String' Nullable='false' />" + " <Property Name='LastName' Type='Edm.String' Nullable='false' />" + " </RowType>" + " </ReturnType>" + " <DefiningExpression>dummy</DefiningExpression>" + " </Function>" + "</Schema>"; var edmItemCollection = new EdmItemCollection(new[] { XmlReader.Create(new StringReader(csdl)) }); var rowTypeUsage = edmItemCollection.GetItems<EdmFunction>().Single(f => f.FullName == "AdventureWorksModel.LastNamesAfter") .ReturnParameters[0] .TypeUsage; TypeUsageVerificationHelper.VerifyTypeUsagesEquivalent(rowTypeUsage.ToLegacyEdmTypeUsage(), rowTypeUsage); }
public static MetadataWorkspace CreateMetadataWorkspace(List<XElement> csdl, List<XElement> ssdl, List<XElement> msl) { EdmItemCollection eic = new EdmItemCollection(csdl.Select(c => c.CreateReader())); StoreItemCollection sic = new StoreItemCollection(ssdl.Select(c => c.CreateReader())); StorageMappingItemCollection smic = new StorageMappingItemCollection(eic, sic, msl.Select(c => c.CreateReader())); // and create metadata workspace based on them. #if !EFOLD MetadataWorkspace workspace = new MetadataWorkspace( () => eic, () => sic, () => smic); #else // Obsolete API MetadataWorkspace workspace = new MetadataWorkspace(); workspace.RegisterItemCollection(eic); workspace.RegisterItemCollection(sic); workspace.RegisterItemCollection(smic); #endif return workspace; }
public void ToLegacyMetadataWorkspace_creates_equivalent_legacy_MetadataWorkspace_for_all_versions() { const string ssdlTemplate = @"<Schema Namespace=""NorthwindEF5Model.Store"" Provider=""System.Data.SqlClient"" ProviderManifestToken=""2008"" Alias=""Self"" xmlns=""{0}"" xmlns:store=""http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator"">" + @" <EntityType Name=""Customers"">" + @" <Key>" + @" <PropertyRef Name=""CustomerID"" />" + @" </Key>" + @" <Property Name=""CustomerID"" Type=""nchar"" MaxLength=""5"" Nullable=""false"" />" + @" <Property Name=""CompanyName"" Type=""nvarchar"" MaxLength=""40"" Nullable=""false"" />" + @" </EntityType>" + @" <EntityContainer Name=""Container"" />" + @"</Schema>"; const string csdlTemplate = @"<Schema xmlns=""{0}"" Namespace=""dummy"">" + @" <EntityContainer Name=""DummyContainer""/>" + @"</Schema>"; const string mslTemplate = @"<Mapping Space=""C-S"" xmlns=""{0}"">" + @" <EntityContainerMapping StorageEntityContainer=""Container"" CdmEntityContainer=""DummyContainer"" />" + @"</Mapping>"; foreach (var version in EntityFrameworkVersion.GetAllVersions()) { var storeItemCollection = Utils.CreateStoreItemCollection( string.Format( ssdlTemplate, SchemaManager.GetSSDLNamespaceName(version))); var edmItemCollection = new EdmItemCollection( new[] { XmlReader.Create( new StringReader( string.Format( csdlTemplate, SchemaManager.GetCSDLNamespaceName(version)))) }); var mappingItemCollection = new StorageMappingItemCollection( edmItemCollection, storeItemCollection, new[] { XmlReader.Create( new StringReader( string.Format( mslTemplate, SchemaManager.GetMSLNamespaceName(version)))) }); var workspace = new MetadataWorkspace( () => edmItemCollection, () => storeItemCollection, () => mappingItemCollection); var legacyWorkspace = workspace.ToLegacyMetadataWorkspace(); Assert.NotNull(legacyWorkspace); var legacyStoreItemCollection = legacyWorkspace.GetItemCollection(LegacyMetadata.DataSpace.SSpace); Assert.Equal( storeItemCollection.GetItems<GlobalItem>().Count, legacyStoreItemCollection.GetItems<LegacyMetadata.GlobalItem>().Count); Assert.NotNull( legacyStoreItemCollection.GetItem<LegacyMetadata.EntityType>("NorthwindEF5Model.Store.Customers")); var legacyEdmItemCollection = (LegacyMetadata.EdmItemCollection)legacyWorkspace.GetItemCollection(LegacyMetadata.DataSpace.CSpace); Assert.NotNull(legacyEdmItemCollection); Assert.Equal(version, EntityFrameworkVersion.DoubleToVersion(legacyEdmItemCollection.EdmVersion)); Assert.NotNull(legacyWorkspace.GetItemCollection(LegacyMetadata.DataSpace.CSSpace)); } }
private void ConcurrencyMode_facet_not_lost_when_converting_to_legacy_TypeUsage() { const string csdl = "<Schema Namespace='AdventureWorksModel' Alias='Self' p1:UseStrongSpatialTypes='false' xmlns:annotation='http://schemas.microsoft.com/ado/2009/02/edm/annotation' xmlns:p1='http://schemas.microsoft.com/ado/2009/02/edm/annotation' xmlns='http://schemas.microsoft.com/ado/2009/11/edm'>" + " <EntityType Name='Customer'>" + " <Key>" + " <PropertyRef Name='Id' />" + " </Key>" + " <Property Type='String' Name='Id' Nullable='false' />" + " <Property Type='String' Name='timestamp' Nullable='false' ConcurrencyMode='Fixed' />" + " </EntityType>" + "</Schema>"; var edmItemCollection = new EdmItemCollection(new[] { XmlReader.Create(new StringReader(csdl)) }); var typeUsage = edmItemCollection .GetItem<EntityType>("AdventureWorksModel.Customer") .Properties.Single(p => p.Name == "timestamp") .TypeUsage; var legacyTypeUsage = typeUsage.ToLegacyEdmTypeUsage(); TypeUsageVerificationHelper.VerifyTypeUsagesEquivalent(legacyTypeUsage, typeUsage); }
internal void CreateVariableConstraints(EntitySetBase extent, MemberDomainMap domainMap, EdmItemCollection edmItemCollection) { CreateVariableConstraintsRecursion(extent.ElementType, new MemberPath(extent), domainMap, edmItemCollection); }
private void CreateVariableConstraintsRecursion( EdmType edmType, MemberPath currentPath, MemberDomainMap domainMap, EdmItemCollection edmItemCollection) { // Add the types can member have, i.e., its type and its subtypes var possibleTypes = new HashSet <EdmType>(); possibleTypes.UnionWith(MetadataHelper.GetTypeAndSubtypesOf(edmType, edmItemCollection, true)); foreach (var possibleType in possibleTypes) { // determine type domain var derivedTypes = new HashSet <EdmType>(); derivedTypes.UnionWith(MetadataHelper.GetTypeAndSubtypesOf(possibleType, edmItemCollection, false)); if (derivedTypes.Count != 0) { var typeCondition = CreateIsOfTypeCondition(currentPath, derivedTypes, domainMap); var typeConditionComplement = BoolExpression.CreateNot(typeCondition); if (false == typeConditionComplement.IsSatisfiable()) { continue; } var structuralType = (StructuralType)possibleType; foreach (var childProperty in structuralType.GetDeclaredOnlyMembers <EdmProperty>()) { var childPath = new MemberPath(currentPath, childProperty); var isScalar = MetadataHelper.IsNonRefSimpleMember(childProperty); if (domainMap.IsConditionMember(childPath) || domainMap.IsProjectedConditionMember(childPath)) { BoolExpression nullCondition; var childDomain = new List <Constant>(domainMap.GetDomain(childPath)); if (isScalar) { nullCondition = BoolExpression.CreateLiteral( new ScalarRestriction( new MemberProjectedSlot(childPath), new Domain(Constant.Undefined, childDomain)), domainMap); } else { nullCondition = BoolExpression.CreateLiteral( new TypeRestriction( new MemberProjectedSlot(childPath), new Domain(Constant.Undefined, childDomain)), domainMap); } // Properties not occuring in type are UNDEFINED AddEquivalence(typeConditionComplement.Tree, nullCondition.Tree); } // recurse into complex types if (false == isScalar) { CreateVariableConstraintsRecursion(childPath.EdmType, childPath, domainMap, edmItemCollection); } } } } }
public EdmMapping(EdmItemCollection conceptual, StoreItemCollection store, Stream storageMappingStream) : this(conceptual, store, XmlReader.Create(storageMappingStream)) { }
/// <summary> /// Creates the MetadataWorkspace for the given context type and base context type. /// </summary> /// <param name="contextType">The type of the context.</param> /// <param name="baseContextType">The base context type (DbContext or ObjectContext).</param> /// <returns>The generated <see cref="MetadataWorkspace"/></returns> public static MetadataWorkspace CreateMetadataWorkspaceFromResources(Type contextType, Type baseContextType) { // get the set of embedded mapping resources for the target assembly and create // a metadata workspace info for each group IEnumerable<string> metadataResourcePaths = FindMetadataResources(contextType.Assembly); IEnumerable<MetadataWorkspaceInfo> workspaceInfos = GetMetadataWorkspaceInfos(metadataResourcePaths); // Search for the correct EntityContainer by name and if found, create // a comlete MetadataWorkspace and return it foreach (var workspaceInfo in workspaceInfos) { EdmItemCollection edmItemCollection = new EdmItemCollection(workspaceInfo.Csdl); Type currentType = contextType; while (currentType != baseContextType && currentType != typeof(object)) { EntityContainer container; if (edmItemCollection.TryGetEntityContainer(currentType.Name, out container)) { StoreItemCollection store = new StoreItemCollection(workspaceInfo.Ssdl); #if DBCONTEXT // This actually means EF6+ MetadataWorkspace workspace = new MetadataWorkspace( () => edmItemCollection, () => store, () => new StorageMappingItemCollection(edmItemCollection, store, workspaceInfo.Msl), () => new ObjectItemCollection()); #else // EF4 StorageMappingItemCollection mapping = new StorageMappingItemCollection(edmItemCollection, store, workspaceInfo.Msl); MetadataWorkspace workspace = new MetadataWorkspace(); workspace.RegisterItemCollection(edmItemCollection); workspace.RegisterItemCollection(store); workspace.RegisterItemCollection(mapping); workspace.RegisterItemCollection(new ObjectItemCollection()); #endif return workspace; } currentType = currentType.BaseType; } } return null; }
internal ViewgenContext( ViewTarget viewTarget, EntitySetBase extent, IList <Cell> extentCells, CqlIdentifiers identifiers, ConfigViewGenerator config, MemberDomainMap queryDomainMap, MemberDomainMap updateDomainMap, StorageEntityContainerMapping entityContainerMapping) { foreach (var cell in extentCells) { Debug.Assert(extent.Equals(cell.GetLeftQuery(viewTarget).Extent)); Debug.Assert(cell.CQuery.NumProjectedSlots == cell.SQuery.NumProjectedSlots); } m_extent = extent; m_viewTarget = viewTarget; m_config = config; m_edmItemCollection = entityContainerMapping.StorageMappingItemCollection.EdmItemCollection; m_entityContainerMapping = entityContainerMapping; m_identifiers = identifiers; // create a copy of updateDomainMap so generation of query views later on is not affected // it is modified in QueryRewriter.AdjustMemberDomainsForUpdateViews updateDomainMap = updateDomainMap.MakeCopy(); // Create a signature generator that handles all the // multiconstant work and generating the signatures var domainMap = viewTarget == ViewTarget.QueryView ? queryDomainMap : updateDomainMap; m_memberMaps = new MemberMaps( viewTarget, MemberProjectionIndex.Create(extent, m_edmItemCollection), queryDomainMap, updateDomainMap); // Create left fragment KB: includes constraints for the extent to be constructed var leftKB = new FragmentQueryKBChaseSupport(); leftKB.CreateVariableConstraints(extent, domainMap, m_edmItemCollection); m_leftFragmentQP = new FragmentQueryProcessor(leftKB); m_rewritingCache = new Dictionary <FragmentQuery, Tile <FragmentQuery> >( FragmentQuery.GetEqualityComparer(m_leftFragmentQP)); // Now using the signatures, create new cells such that // "extent's" query (C or S) is described in terms of multiconstants if (!CreateLeftCellWrappers(extentCells, viewTarget)) { return; } // Create right fragment KB: includes constraints for all extents and association roles of right queries var rightKB = new FragmentQueryKBChaseSupport(); var rightDomainMap = viewTarget == ViewTarget.QueryView ? updateDomainMap : queryDomainMap; foreach (var leftCellWrapper in m_cellWrappers) { var rightExtent = leftCellWrapper.RightExtent; rightKB.CreateVariableConstraints(rightExtent, rightDomainMap, m_edmItemCollection); rightKB.CreateAssociationConstraints(rightExtent, rightDomainMap, m_edmItemCollection); } if (m_viewTarget == ViewTarget.UpdateView) { CreateConstraintsForForeignKeyAssociationsAffectingThisWrapper(rightKB, rightDomainMap); } m_rightFragmentQP = new FragmentQueryProcessor(rightKB); // Check for concurrency control tokens if (m_viewTarget == ViewTarget.QueryView) { CheckConcurrencyControlTokens(); } // For backward compatibility - // order wrappers by increasing domain size, decreasing number of attributes m_cellWrappers.Sort(LeftCellWrapper.Comparer); }
internal static XElement ConstructEntityContainer( EdmItemCollection edm, string databaseSchemaName, string csdlNamespace, string ssdlNamespace) { var entityContainerElement = new XElement( _ssdl + "EntityContainer", new XAttribute("Name", OutputGeneratorHelpers.ConstructStorageEntityContainerName(csdlNamespace))); #region Constructing EntitySets // In TPT, we need to create the SSDL EntitySets from the EntityTypes; we create another table for the derived type. foreach (var entityType in edm.GetAllEntityTypes()) { var entitySetElement = ConstructEntitySet( ssdlNamespace, OutputGeneratorHelpers.GetStorageEntityTypeName(entityType, edm), OutputGeneratorHelpers.GetStorageEntityTypeName(entityType, edm), "Tables", databaseSchemaName); // we would also tack on DefiningQueries here if we wanted entityContainerElement.Add(entitySetElement); } // Find all *:* Associations and create EntitySets in the SSDL foreach (var associationSet in edm.GetAllAssociationSets().Where(set => set.GetAssociation().IsManyToMany())) { var entitySetElement = ConstructEntitySet( ssdlNamespace, associationSet.Name, associationSet.ElementType.Name, "Tables", databaseSchemaName); entityContainerElement.Add(entitySetElement); } #endregion #region Constructing AssociationSets foreach (var associationSet in edm.GetAllAssociationSets()) { var assoc = associationSet.GetAssociation(); if (assoc.GetEnd1() != null && assoc.GetEnd2() != null) { // *:* C-Space associations: we will have two S-space associations bound to the pair table corresponding to each end if (assoc.IsManyToMany()) { // create an association from the first end to the pair table var associationSet1Element = ConstructAssociationSet( ssdlNamespace, OutputGeneratorHelpers.GetStorageAssociationSetNameFromManyToMany(associationSet, assoc.GetEnd1()), OutputGeneratorHelpers.GetStorageAssociationNameFromManyToMany(assoc.GetEnd1()), assoc.GetEnd1().Name, OutputGeneratorHelpers.GetStorageEntityTypeName(assoc.GetEnd1().GetEntityType(), edm), assoc.Name, associationSet.Name); // create an association from the second end to the pair table var associationSet2Element = ConstructAssociationSet( ssdlNamespace, OutputGeneratorHelpers.GetStorageAssociationSetNameFromManyToMany(associationSet, assoc.GetEnd2()), OutputGeneratorHelpers.GetStorageAssociationNameFromManyToMany(assoc.GetEnd2()), assoc.GetEnd2().Name, OutputGeneratorHelpers.GetStorageEntityTypeName(assoc.GetEnd2().GetEntityType(), edm), assoc.Name, associationSet.Name); entityContainerElement.Add(associationSet1Element); entityContainerElement.Add(associationSet2Element); } // All other associations: we essentially mirror the C-space associations else { var associationSetElement = ConstructAssociationSet( ssdlNamespace, associationSet.Name, assoc.Name, assoc.GetEnd1().Name, OutputGeneratorHelpers.GetStorageEntityTypeName(assoc.GetEnd1().GetEntityType(), edm), assoc.GetEnd2().Name, OutputGeneratorHelpers.GetStorageEntityTypeName(assoc.GetEnd2().GetEntityType(), edm)); entityContainerElement.Add(associationSetElement); } } } // Now we will construct AssociationSets with PK:PK associations based off of inheritance foreach (var derivedType in edm.GetAllEntityTypes().Where(et => et.BaseType != null)) { entityContainerElement.Add( ConstructAssociationSet( ssdlNamespace, String.Format( CultureInfo.CurrentCulture, Resources.CodeViewFKConstraintDerivedType, derivedType.Name, derivedType.BaseType.Name), String.Format( CultureInfo.CurrentCulture, Resources.CodeViewFKConstraintDerivedType, derivedType.Name, derivedType.BaseType.Name), derivedType.BaseType.Name, OutputGeneratorHelpers.GetStorageEntityTypeName(derivedType.BaseType as EntityType, edm), derivedType.Name, OutputGeneratorHelpers.GetStorageEntityTypeName(derivedType, edm))); } #endregion var csdlEntityContainer = edm.GetItems <EntityContainer>().FirstOrDefault(); Debug.Assert(csdlEntityContainer != null, "Could not find the CSDL EntityContainer to migrate extended properties"); if (csdlEntityContainer != null) { OutputGeneratorHelpers.CopyExtendedPropertiesToSsdlElement(csdlEntityContainer, entityContainerElement); } return(entityContainerElement); }
internal static List <XElement> ConstructAssociations(EdmItemCollection edm, string ssdlNamespace) { var associations = new List <XElement>(); // Ignore *:* associations for now, just translate the CSDL Associations into SSDL Associations foreach (var association in edm.GetItems <AssociationType>().Where(a => !a.IsManyToMany())) { var associationElement = new XElement(_ssdl + "Association", new XAttribute("Name", association.Name)); var principalEnd = association.GetPrincipalEnd(); var dependentEnd = association.GetDependentEnd(); // 1. If we have a PK:PK relationship that has a ref constraint, then the multiplicity of the // dependent end will always be 0..1. // 2. If we have a PK:PK relationship without a ref constraint, the multiplicity will // always be *. // 3. If we have any other relationship, regardless of the ref constraint, we simply // mirror the multiplicity from the C-side. if (principalEnd != null && dependentEnd != null) { foreach (var end in association.AssociationEndMembers) { var entityType = end.GetEntityType(); var multiplicity = TranslateMultiplicity(end.RelationshipMultiplicity); if (end == dependentEnd && association.IsPKToPK()) { multiplicity = (association.ReferentialConstraints.Count > 0) ? TranslateMultiplicity(RelationshipMultiplicity.ZeroOrOne) : TranslateMultiplicity(RelationshipMultiplicity.Many); } var associationEnd = new XElement( _ssdl + "End", new XAttribute("Role", end.Name), new XAttribute("Type", ssdlNamespace + "." + OutputGeneratorHelpers.GetStorageEntityTypeName(entityType, edm)), new XAttribute("Multiplicity", multiplicity)); // Now we will attempt to add an OnDelete="Cascade" rule if (end.GetOnDelete() == OperationAction.Cascade) { associationEnd.Add( new XElement( _ssdl + "OnDelete", new XAttribute("Action", "Cascade"))); } associationElement.Add(associationEnd); } } // 1. If we have an existing ref constraint in the C-side, then we will simply mirror that in the SSDL. // 2. If we have a non *:* association without a ref constraint, then we specify the foreign keys' names of // the dependent entity type (which is the principal entity type's keys' names) if (association.ReferentialConstraints.Count > 0) { var refConstraint = association.ReferentialConstraints.FirstOrDefault(); if (refConstraint != null) { associationElement.Add( ConstructReferentialConstraintInternal( refConstraint.FromRole.Name, refConstraint.FromProperties.Select(fp => fp.Name), refConstraint.ToRole.Name, refConstraint.ToProperties.Select(tp => tp.Name))); } } else { associationElement.Add( ConstructReferentialConstraint( principalEnd.Name, principalEnd, dependentEnd.Name, dependentEnd)); } OutputGeneratorHelpers.CopyExtendedPropertiesToSsdlElement(association, associationElement); associations.Add(associationElement); } // Now let's tackle the *:* Associations. A *:* conceptual Association means that there is actually a pair table // in the database, and two relationships -- one from the first end to the pair table and another from the pair table // to the second end. // For *:* associations, we'll also identify any extended properties and migrate them to _both_ associations on the S-side. foreach (var m2mAssoc in edm.GetItems <AssociationType>().Where(a => a.IsManyToMany())) { if (m2mAssoc.GetEnd1() != null && m2mAssoc.GetEnd2() != null) { var entityType1 = m2mAssoc.GetEnd1().GetEntityType(); var entityType2 = m2mAssoc.GetEnd2().GetEntityType(); if (entityType1 != null && entityType2 != null) { var associationElement1 = new XElement( _ssdl + "Association", new XAttribute("Name", OutputGeneratorHelpers.GetStorageAssociationNameFromManyToMany(m2mAssoc.GetEnd1()))); associationElement1.Add( new XElement( _ssdl + "End", new XAttribute("Role", m2mAssoc.GetEnd1().Name), new XAttribute( "Type", ssdlNamespace + "." + OutputGeneratorHelpers.GetStorageEntityTypeName(entityType1, edm)), new XAttribute("Multiplicity", "1"))); associationElement1.Add( new XElement( _ssdl + "End", new XAttribute("Role", m2mAssoc.Name), new XAttribute("Type", ssdlNamespace + "." + m2mAssoc.Name), new XAttribute("Multiplicity", "*"))); associationElement1.Add( ConstructReferentialConstraint(m2mAssoc.GetEnd1().Name, m2mAssoc.GetEnd1(), m2mAssoc.Name, m2mAssoc.GetEnd2())); OutputGeneratorHelpers.CopyExtendedPropertiesToSsdlElement(m2mAssoc, associationElement1); associations.Add(associationElement1); var associationElement2 = new XElement( _ssdl + "Association", new XAttribute("Name", OutputGeneratorHelpers.GetStorageAssociationNameFromManyToMany(m2mAssoc.GetEnd2()))); associationElement2.Add( new XElement( _ssdl + "End", new XAttribute("Role", m2mAssoc.Name), new XAttribute("Type", ssdlNamespace + "." + m2mAssoc.Name), new XAttribute("Multiplicity", "*"))); associationElement2.Add( new XElement( _ssdl + "End", new XAttribute("Role", m2mAssoc.GetEnd2().Name), new XAttribute( "Type", ssdlNamespace + "." + OutputGeneratorHelpers.GetStorageEntityTypeName(entityType2, edm)), new XAttribute("Multiplicity", "1"))); associationElement2.Add( ConstructReferentialConstraint(m2mAssoc.GetEnd2().Name, m2mAssoc.GetEnd2(), m2mAssoc.Name, m2mAssoc.GetEnd1())); OutputGeneratorHelpers.CopyExtendedPropertiesToSsdlElement(m2mAssoc, associationElement2); associations.Add(associationElement2); } } } // Finally, we will add PK:PK Associations for any inheritance found in the conceptual. These will translate into PK constraints // in the DDL which will round-trip back in an identifiable way. Base Type's role in this association will have OnDelete action // set to Cascade so that if you delete a row from the base table, any corresponding rows in the child table will also be deleted. foreach (var derivedType in edm.GetAllEntityTypes().Where(et => et.BaseType != null)) { var pkAssociation = new XElement( _ssdl + "Association", new XAttribute( "Name", String.Format( CultureInfo.CurrentCulture, Resources.CodeViewFKConstraintDerivedType, derivedType.Name, derivedType.BaseType.Name))); var baseTypeRole = new XElement( _ssdl + "End", new XAttribute("Role", derivedType.BaseType.Name), new XAttribute( "Type", ssdlNamespace + "." + OutputGeneratorHelpers.GetStorageEntityTypeName(derivedType.BaseType as EntityType, edm)), new XAttribute("Multiplicity", "1")); pkAssociation.Add(baseTypeRole); baseTypeRole.Add(new XElement(_ssdl + "OnDelete", new XAttribute("Action", "Cascade"))); pkAssociation.Add( new XElement( _ssdl + "End", new XAttribute("Role", derivedType.Name), new XAttribute("Type", ssdlNamespace + "." + OutputGeneratorHelpers.GetStorageEntityTypeName(derivedType, edm)), new XAttribute("Multiplicity", "0..1"))); pkAssociation.Add( ConstructReferentialConstraintInternal( derivedType.BaseType.Name, derivedType.GetRootOrSelf().GetKeyProperties().Select(k => k.Name), derivedType.Name, derivedType.GetRootOrSelf().GetKeyProperties().Select(k => k.Name))); associations.Add(pkAssociation); } return(associations); }
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); }
// effects: Returns all the concurrency token members in superType and its subtypes internal static Set <EdmMember> GetConcurrencyMembersForTypeHierarchy(EntityTypeBase superType, EdmItemCollection edmItemCollection) { Set <EdmMember> result = new Set <EdmMember>(); foreach (StructuralType type in GetTypeAndSubtypesOf(superType, edmItemCollection, true /*includeAbstractTypes */)) { // Go through all the members -- Can call Members instead of AllMembers since we are // running through the whole hierarchy foreach (EdmMember member in type.Members) { // check for the concurrency facet ConcurrencyMode concurrencyMode = GetConcurrencyMode(member); if (concurrencyMode == ConcurrencyMode.Fixed) { result.Add(member); } } } return(result); }
/// <summary> /// Builds an undirected graph (represented as a directional graph with reciprocal navigation edges) of the all the types in the workspace. /// This is used to traverse inheritance hierarchy up and down. /// O(n), where n=number of types /// </summary> /// <returns>A dictionary of type t -> set of types {s}, such that there is an edge between t and elem(s) iff t and s are related DIRECTLY via inheritance (child or parent type) </returns> internal static Dictionary <EntityType, Set <EntityType> > BuildUndirectedGraphOfTypes(EdmItemCollection edmItemCollection) { Dictionary <EntityType, Set <EntityType> > graph = new Dictionary <EntityType, Set <EntityType> >(); IEnumerable <EntityType> typesInWorkSpace = edmItemCollection.GetItems <EntityType>(); foreach (EntityType childType in typesInWorkSpace) { if (childType.BaseType == null) //root type { continue; } EntityType parentType = childType.BaseType as EntityType; Debug.Assert(parentType != null, "Parent type not Entity Type ??"); AddDirectedEdgeBetweenEntityTypes(graph, childType, parentType); AddDirectedEdgeBetweenEntityTypes(graph, parentType, childType); } return(graph); }
public static StorageMappingItemCollection CreateStorageMappingItemCollection(EdmItemCollection edmCollection, StoreItemCollection storeCollection, IEnumerable <XmlReader> readers, out IList <EdmSchemaError> errors) { return(new StorageMappingItemCollection(edmCollection, storeCollection, readers, null, out errors)); }
internal void TestPipeline( string testName, EdmItemCollection csdlInput, string workflowFilePath, Version versionOfCsdl, Func <WorkflowApplicationCompletedEventArgs, object> postInvokeCallback) { const string existingMsl = "<Mapping Space='C-S' xmlns='http://schemas.microsoft.com/ado/2008/09/mapping/cs'>" + " <EntityContainerMapping StorageEntityContainer='Model1StoreContainer' CdmEntityContainer='Model1Container' />" + "</Mapping>"; const string existingSsdl = "<Schema Namespace='Store' Alias='Self' Provider='System.Data.SqlClient' ProviderManifestToken='2005' xmlns='http://schemas.microsoft.com/ado/2006/04/edm/ssdl' />"; Exception savedException = null; var workflowCompleted = new AutoResetEvent(false); var completedHandler = new Action <WorkflowApplicationCompletedEventArgs>( e => { try { var result = (string)postInvokeCallback(e); Assert.AreEqual( TestUtils.LoadEmbeddedResource("EFDesigner.InProcTests.Baselines." + testName + ".bsl"), result); } catch (Exception ex) { // save off the exception, return out of the completion handler. If we throw here // the wrong thread will catch the exception savedException = ex; } finally { workflowCompleted.Set(); } } ); var unhandledExceptionHandler = new Func <WorkflowApplicationUnhandledExceptionEventArgs, UnhandledExceptionAction>( e => { if (e.UnhandledException != null) { Console.WriteLine(e.UnhandledException); savedException = e.UnhandledException; } workflowCompleted.Set(); return(UnhandledExceptionAction.Terminate); } ); var resolvedWorkflowFileInfo = DatabaseGenerationEngine.ResolveAndValidateWorkflowPath(null, workflowFilePath); var workflowInstance = DatabaseGenerationEngine.CreateDatabaseScriptGenerationWorkflow( null, null, null, resolvedWorkflowFileInfo, "$(VSEFTools)\\DBGen\\SSDLToSQL10.tt", csdlInput, existingSsdl, existingMsl, "dbo", "TestDb", "System.Data.SqlClient", null, "2005", versionOfCsdl, completedHandler, unhandledExceptionHandler); // Kick off the workflow workflowInstance.Run(); // Block this thread until the AutoResetEvent receives a signal for synchronous behavior (just in case) workflowCompleted.WaitOne(); // Check to see if an exception was set, if so, throw it so the test framework can handle it if (savedException != null) { throw savedException; } }
private static MetadataWorkspace CreateWrappedMetadataWorkspace(string metadata, IEnumerable<string> wrapperProviderNames) { // parse Metadata keyword and load CSDL,SSDL,MSL files into XElement structures... var csdl = new List<XElement>(); var ssdl = new List<XElement>(); var msl = new List<XElement>(); ParseMetadata(metadata, csdl, ssdl, msl); // fix all SSDL files by changing 'Provider' to our provider and modifying foreach (var ssdlFile in ssdl) { foreach (string providerName in wrapperProviderNames) { ssdlFile.Attribute("ProviderManifestToken").Value = ssdl[0].Attribute("Provider").Value + ";" + ssdlFile.Attribute("ProviderManifestToken").Value; ssdlFile.Attribute("Provider").Value = providerName; } } // load item collections from XML readers created from XElements... EdmItemCollection eic = new EdmItemCollection(csdl.Select(c => c.CreateReader())); StoreItemCollection sic = new StoreItemCollection(ssdl.Select(c => c.CreateReader())); StorageMappingItemCollection smic = new StorageMappingItemCollection(eic, sic, msl.Select(c => c.CreateReader())); // and create metadata workspace based on them. #if !EFOLD MetadataWorkspace workspace = new MetadataWorkspace( () => eic, () => sic, () => smic); #else // Obsolete API MetadataWorkspace workspace = new MetadataWorkspace(); workspace.RegisterItemCollection(eic); workspace.RegisterItemCollection(sic); workspace.RegisterItemCollection(smic); #endif return workspace; }
internal static List <XElement> ConstructAssociationSetMappings( EdmItemCollection edm, string csdlNamespace, Version targetFrameworkVersion) { 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", 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.GetFkName(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.GetFkName(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); }