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