private static void MoveAssociationSetMappingDependents(
            StorageAssociationSetMapping associationSetMapping,
            StorageEndPropertyMapping dependentMapping,
            EntitySet toSet,
            bool useExistingColumns)
        {
            DebugCheck.NotNull(associationSetMapping);
            DebugCheck.NotNull(dependentMapping);
            DebugCheck.NotNull(toSet);

            var toTable = toSet.ElementType;

            dependentMapping.PropertyMappings.Each(
                pm =>
            {
                var oldColumn = pm.ColumnProperty;

                pm.ColumnProperty
                    = TableOperations.MoveColumnAndAnyConstraints(
                          associationSetMapping.Table, toTable, oldColumn, useExistingColumns);

                associationSetMapping.ColumnConditions
                .Where(cc => cc.ColumnProperty == oldColumn)
                .Each(cc => cc.ColumnProperty = pm.ColumnProperty);
            });

            associationSetMapping.StoreEntitySet = toSet;
        }
        private bool TryGetWithRelationship(StorageAssociationSetMapping colocatedAssociationSetMap,
                                            EntitySetBase thisExtent,
                                            MemberPath sRootNode,
                                            ref List <SlotInfo> foreignKeySlots,
                                            out WithRelationship withRelationship)
        {
            Debug.Assert(foreignKeySlots != null);
            withRelationship = null;

            //Get the map for foreign key end
            StorageEndPropertyMapping foreignKeyEndMap = GetForeignKeyEndMapFromAssocitionMap(colocatedAssociationSetMap, thisExtent);

            if (foreignKeyEndMap == null || foreignKeyEndMap.EndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
            {
                return(false);
            }

            AssociationEndMember toEnd             = (AssociationEndMember)foreignKeyEndMap.EndMember;
            AssociationEndMember fromEnd           = MetadataHelper.GetOtherAssociationEnd(toEnd);
            EntityType           toEndEntityType   = (EntityType)((RefType)(toEnd.TypeUsage.EdmType)).ElementType;
            EntityType           fromEndEntityType = (EntityType)(((RefType)fromEnd.TypeUsage.EdmType).ElementType);

            // Get the member path for AssociationSet
            AssociationSet associationSet = (AssociationSet)colocatedAssociationSetMap.Set;
            MemberPath     prefix         = new MemberPath(associationSet, toEnd);

            // Collect the member paths for edm scalar properties that belong to the target entity key.
            // These will be used as part of WITH RELATIONSHIP.
            // Get the key properties from edm type since the query parser depends on the order of key members
            IEnumerable <StorageScalarPropertyMapping> propertyMaps = foreignKeyEndMap.Properties.Cast <StorageScalarPropertyMapping>();
            List <MemberPath> toEndEntityKeyMemberPaths             = new List <MemberPath>();

            foreach (EdmProperty edmProperty in toEndEntityType.KeyMembers)
            {
                IEnumerable <StorageScalarPropertyMapping> scalarPropertyMaps = propertyMaps.Where(propMap => (propMap.EdmProperty.Equals(edmProperty)));
                Debug.Assert(scalarPropertyMaps.Count() == 1, "Can't Map the same column multiple times in the same end");
                StorageScalarPropertyMapping scalarPropertyMap = scalarPropertyMaps.First();

                // Create SlotInfo for Freign Key member that needs to be projected.
                MemberProjectedSlot sSlot            = new MemberProjectedSlot(new MemberPath(sRootNode, scalarPropertyMap.ColumnProperty));
                MemberPath          endMemberKeyPath = new MemberPath(prefix, edmProperty);
                toEndEntityKeyMemberPaths.Add(endMemberKeyPath);
                foreignKeySlots.Add(new SlotInfo(true, true, sSlot, endMemberKeyPath));
            }

            // Parent assignable from child: Ensures they are in the same hierarchy.
            if (thisExtent.ElementType.IsAssignableFrom(fromEndEntityType))
            {
                // Now create the WITH RELATIONSHIP with all the needed info.
                withRelationship = new WithRelationship(associationSet, fromEnd, fromEndEntityType, toEnd, toEndEntityType, toEndEntityKeyMemberPaths);
                return(true);
            }
            else
            {
                return(false);
            }
        }
        private void WriteAssociationEndMappingElement(StorageEndPropertyMapping endMapping)
        {
            _xmlWriter.WriteStartElement(StorageMslConstructs.EndPropertyMappingElement);
            _xmlWriter.WriteAttributeString(StorageMslConstructs.EndPropertyMappingNameAttribute, endMapping.EndMember.Name);

            foreach (var propertyMapping in endMapping.PropertyMappings)
            {
                WriteScalarPropertyElement(
                    propertyMapping.EdmProperty,
                    propertyMapping.ColumnProperty);
            }

            _xmlWriter.WriteEndElement();
        }
예제 #4
0
        private IEnumerable <EdmProperty> GenerateIndependentForeignKeyColumns(
            EntityType principalEntityType,
            EntityType dependentEntityType,
            StorageAssociationSetMapping associationSetMapping,
            StorageEndPropertyMapping associationEndMapping,
            EntityType dependentTable,
            bool isPrimaryKeyColumn,
            NavigationProperty principalNavigationProperty)
        {
            DebugCheck.NotNull(principalEntityType);
            DebugCheck.NotNull(associationEndMapping);
            DebugCheck.NotNull(dependentTable);

            foreach (var property in principalEntityType.KeyProperties())
            {
                var columnName
                    = ((principalNavigationProperty != null)
                           ? principalNavigationProperty.Name
                           : principalEntityType.Name) + "_" + property.Name;

                var foreignKeyColumn
                    = MapTableColumn(property, columnName, false);

                dependentTable.AddColumn(foreignKeyColumn);

                if (isPrimaryKeyColumn)
                {
                    dependentTable.AddKeyMember(foreignKeyColumn);
                }

                foreignKeyColumn.Nullable
                    = associationEndMapping.EndMember.IsOptional() ||
                      (associationEndMapping.EndMember.IsRequired() &&
                       dependentEntityType.BaseType != null);

                foreignKeyColumn.StoreGeneratedPattern = StoreGeneratedPattern.None;

                yield return(foreignKeyColumn);

                associationEndMapping.AddProperty(new StorageScalarPropertyMapping(property, foreignKeyColumn));

                if (foreignKeyColumn.Nullable)
                {
                    associationSetMapping
                    .AddColumnCondition(new StorageConditionPropertyMapping(null, foreignKeyColumn, null, false));
                }
            }
        }
예제 #5
0
        private void GenerateIndependentForeignKeyConstraint(
            DbDatabaseMapping databaseMapping,
            EntityType principalEntityType,
            EntityType dependentEntityType,
            EntityType dependentTable,
            StorageAssociationSetMapping associationSetMapping,
            StorageEndPropertyMapping associationEndMapping,
            string name,
            AssociationEndMember principalEnd,
            bool isPrimaryKeyColumn = false)
        {
            DebugCheck.NotNull(databaseMapping);
            DebugCheck.NotNull(principalEntityType);
            DebugCheck.NotNull(dependentTable);
            DebugCheck.NotNull(associationEndMapping);
            DebugCheck.NotEmpty(name);

            var principalTable
                = GetEntityTypeMappingInHierarchy(databaseMapping, principalEntityType)
                  .MappingFragments
                  .Single()
                  .Table;

            var foreignKeyConstraint
                = new ForeignKeyBuilder(databaseMapping.Database, name)
                {
                PrincipalTable = principalTable,
                DeleteAction   = associationEndMapping.EndMember.DeleteBehavior != OperationAction.None
                                             ? associationEndMapping.EndMember.DeleteBehavior
                                             : OperationAction.None
                };

            var principalNavigationProperty
                = databaseMapping.Model.GetEntityTypes()
                  .SelectMany(e => e.DeclaredNavigationProperties)
                  .SingleOrDefault(n => n.ResultEnd == principalEnd);

            dependentTable.AddForeignKey(foreignKeyConstraint);

            foreignKeyConstraint.DependentColumns = GenerateIndependentForeignKeyColumns(
                principalEntityType,
                dependentEntityType,
                associationSetMapping,
                associationEndMapping,
                dependentTable,
                isPrimaryKeyColumn,
                principalNavigationProperty);
        }
        // requires: "properties" corresponds to all the properties that are
        // inside cNode.Value, e.g., cNode corresponds to an extent Person,
        // properties contains all the properties inside Person (recursively)
        // effects: Given C-side and S-side Cell Query for a cell, generates
        // the projected slots on both sides corresponding to
        // properties. Also updates the C-side whereclause corresponding to
        // discriminator properties on the C-side, e.g, isHighPriority
        private void ExtractProperties(IEnumerable <StoragePropertyMapping> properties,
                                       MemberPath cNode, List <ProjectedSlot> cSlots,
                                       ref BoolExpression cQueryWhereClause,
                                       MemberPath sRootExtent,
                                       List <ProjectedSlot> sSlots,
                                       ref BoolExpression sQueryWhereClause)
        {
            // For each property mapping, we add an entry to the C and S cell queries
            foreach (StoragePropertyMapping propMap in properties)
            {
                StorageScalarPropertyMapping    scalarPropMap              = propMap as StorageScalarPropertyMapping;
                StorageComplexPropertyMapping   complexPropMap             = propMap as StorageComplexPropertyMapping;
                StorageEndPropertyMapping       associationEndPropertypMap = propMap as StorageEndPropertyMapping;
                StorageConditionPropertyMapping conditionMap = propMap as StorageConditionPropertyMapping;

                Debug.Assert(scalarPropMap != null ||
                             complexPropMap != null ||
                             associationEndPropertypMap != null ||
                             conditionMap != null, "Unimplemented property mapping");

                if (scalarPropMap != null)
                {
                    Debug.Assert(scalarPropMap.ColumnProperty != null, "ColumnMember for a Scalar Property can not be null");
                    // Add an attribute node to node

                    MemberPath cAttributeNode = new MemberPath(cNode, scalarPropMap.EdmProperty);
                    // Add a column (attribute) node the sQuery
                    // unlike the C side, there is no nesting. Hence we
                    // did not need an internal node
                    MemberPath sAttributeNode = new MemberPath(sRootExtent, scalarPropMap.ColumnProperty);
                    cSlots.Add(new MemberProjectedSlot(cAttributeNode));
                    sSlots.Add(new MemberProjectedSlot(sAttributeNode));
                }

                // Note: S-side constants are not allowed since they can cause
                // problems -- for example, if such a cell says 5 for the
                // third field, we cannot guarantee the fact that an
                // application may not set that field to 7 in the C-space

                // Check if the property mapping is for a complex types
                if (complexPropMap != null)
                {
                    foreach (StorageComplexTypeMapping complexTypeMap in complexPropMap.TypeMappings)
                    {
                        // Create a node for the complex type property and call recursively
                        MemberPath complexMemberNode = new MemberPath(cNode, complexPropMap.EdmProperty);
                        //Get the list of types that this type map represents
                        Set <EdmType> allTypes = new Set <EdmType>();
                        // Gather a set of all explicit types for an entity
                        // type mapping in allTypes.
                        IEnumerable <EdmType> exactTypes = Helpers.AsSuperTypeList <ComplexType, EdmType>(complexTypeMap.Types);
                        allTypes.AddRange(exactTypes);
                        foreach (EdmType type in complexTypeMap.IsOfTypes)
                        {
                            allTypes.AddRange(MetadataHelper.GetTypeAndSubtypesOf(type, m_containerMapping.StorageMappingItemCollection.EdmItemCollection, false /*includeAbstractTypes*/));
                        }
                        BoolExpression complexInTypes = BoolExpression.CreateLiteral(new TypeRestriction(complexMemberNode, allTypes), null);
                        cQueryWhereClause = BoolExpression.CreateAnd(cQueryWhereClause, complexInTypes);
                        // Now extract the properties of the complex type
                        // (which could have other complex types)
                        ExtractProperties(complexTypeMap.AllProperties, complexMemberNode, cSlots,
                                          ref cQueryWhereClause, sRootExtent, sSlots, ref sQueryWhereClause);
                    }
                }

                // Check if the property mapping is for an associaion
                if (associationEndPropertypMap != null)
                {
                    // create join tree node representing this relation end
                    MemberPath associationEndNode = new MemberPath(cNode, associationEndPropertypMap.EndMember);
                    // call recursively
                    ExtractProperties(associationEndPropertypMap.Properties, associationEndNode, cSlots,
                                      ref cQueryWhereClause, sRootExtent, sSlots, ref sQueryWhereClause);
                }

                //Check if the this is a condition and add it to the Where clause
                if (conditionMap != null)
                {
                    if (conditionMap.ColumnProperty != null)
                    {
                        //Produce a Condition Expression for the Condition Map.
                        BoolExpression conditionExpression = GetConditionExpression(sRootExtent, conditionMap);
                        //Add the condition expression to the exisiting S side Where clause using an "And"
                        sQueryWhereClause = BoolExpression.CreateAnd(sQueryWhereClause, conditionExpression);
                    }
                    else
                    {
                        Debug.Assert(conditionMap.EdmProperty != null);
                        //Produce a Condition Expression for the Condition Map.
                        BoolExpression conditionExpression = GetConditionExpression(cNode, conditionMap);
                        //Add the condition expression to the exisiting C side Where clause using an "And"
                        cQueryWhereClause = BoolExpression.CreateAnd(cQueryWhereClause, conditionExpression);
                    }
                }
            }
        }