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 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); }