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);
            }
        }
Пример #2
0
        private void WritePropertyMapping(StorageScalarPropertyMapping scalarPropertyMapping)
        {
            DebugCheck.NotNull(scalarPropertyMapping);

            WriteScalarPropertyElement(scalarPropertyMapping.EdmProperty, scalarPropertyMapping.ColumnProperty);
        }
        // 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);
                    }
                }
            }
        }
 private void WritePropertyMapping(StorageScalarPropertyMapping scalarPropertyMapping)
 {
     WriteScalarPropertyElement(scalarPropertyMapping.EdmProperty, scalarPropertyMapping.ColumnProperty);
 }