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);
        }
Пример #5
0
 internal void CreateVariableConstraints(EntitySetBase extent, MemberDomainMap domainMap, EdmItemCollection edmItemCollection)
 {
     CreateVariableConstraintsRecursion(extent.ElementType, new MemberPath(extent), domainMap, edmItemCollection);
 }
Пример #6
0
        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);
                        }
                    }
                }
            }
        }
Пример #7
0
 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;
        }
Пример #9
0
        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);
        }
Пример #10
0
        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);
        }
Пример #11
0
        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);
        }
Пример #12
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);
        }
Пример #13
0
        // 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);
        }
Пример #14
0
        /// <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;
        }
Пример #18
0
        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);
        }