/// <summary> /// Returns the Association in an AssociationSet /// </summary> /// <param name="associationSet">The AssociationSet.</param> /// <returns>The Association.</returns> public static AssociationType GetAssociation(this AssociationSet associationSet) { return(associationSet.ElementType); }
private void InitializeEntitySet(EntitySetBase entitySetBase, MetadataWorkspace workspace) { StorageEntityContainerMapping mapping = (StorageEntityContainerMapping)m_mappingCollection.GetMap(entitySetBase.EntityContainer); // make sure views have been generated for this sub-graph (trigger generation of the sub-graph // by retrieving a view for one of its components; not actually using the view here) if (mapping.HasViews) { m_mappingCollection.GetGeneratedView(entitySetBase, workspace); } Set <EntitySet> affectedTables = new Set <EntitySet>(); if (null != mapping) { Set <EdmMember> isNullConditionColumns = new Set <EdmMember>(); // find extent in the container mapping StorageSetMapping setMapping; if (entitySetBase.BuiltInTypeKind == BuiltInTypeKind.EntitySet) { setMapping = mapping.GetEntitySetMapping(entitySetBase.Name); // Check for members that have result bindings in a function mapping. If a // function returns the member values, it indicates they are server-generated m_serverGenProperties.Unite(GetMembersWithResultBinding((StorageEntitySetMapping)setMapping)); } else if (entitySetBase.BuiltInTypeKind == BuiltInTypeKind.AssociationSet) { setMapping = mapping.GetRelationshipSetMapping(entitySetBase.Name); } else { Debug.Fail("unexpected extent type " + entitySetBase.BuiltInTypeKind); throw EntityUtil.NotSupported(); } // gather interesting tables, columns and properties from mapping fragments foreach (StorageMappingFragment mappingFragment in GetMappingFragments(setMapping)) { affectedTables.Add(mappingFragment.TableSet); // get all property mappings to figure out if anything is server generated m_serverGenProperties.AddRange(FindServerGenMembers(mappingFragment)); // get all columns participating in is null conditions isNullConditionColumns.AddRange(FindIsNullConditionColumns(mappingFragment)); } if (0 < isNullConditionColumns.Count) { // gather is null condition properties based on is null condition columns foreach (StorageMappingFragment mappingFragment in GetMappingFragments(setMapping)) { m_isNullConditionProperties.AddRange(FindPropertiesMappedToColumns(isNullConditionColumns, mappingFragment)); } } } m_affectedTables.Add(entitySetBase, affectedTables.MakeReadOnly()); InitializeFunctionMappingTranslators(entitySetBase, mapping); // for association sets, initialize AssociationSetMetadata if no function has claimed ownership // of the association yet if (entitySetBase.BuiltInTypeKind == BuiltInTypeKind.AssociationSet) { AssociationSet associationSet = (AssociationSet)entitySetBase; if (!m_associationSetMetadata.ContainsKey(associationSet)) { m_associationSetMetadata.Add(associationSet, new AssociationSetMetadata( m_affectedTables[associationSet], associationSet, workspace)); } } }
private static AssociationSetEnd GetAssociationSetEndForForeignKeyTable(AssociationSet associationSet) { var constraint = GetReferentialConstraint(associationSet); return(associationSet.AssociationSetEnds.GetValue(constraint.ToRole.Name, false)); }
public MappingAssociationSet(EditingContext context, AssociationSet assocSet, MappingEFElement parent) : base(context, assocSet, parent) { }
/// <summary> /// Returns an array of size <see cref="TotalSlots"/> which indicates the slots that are needed to constuct value at <paramref name="caseMemberPath"/>, /// e.g., CPerson may need pid and name (say slots 2 and 5 - then bools[2] and bools[5] will be true. /// </summary> /// <param name="caseMemberPath">must be part of <see cref="m_caseStatements"/></param> private void GetRequiredSlotsForCaseMember(MemberPath caseMemberPath, bool[] requiredSlots) { Debug.Assert(true == m_caseStatements.ContainsKey(caseMemberPath), "Constructing case for regular field?"); Debug.Assert(requiredSlots.Length == TotalSlots, "Invalid array size for populating required slots"); CaseStatement statement = m_caseStatements[caseMemberPath]; // Find the required slots from the when then clause conditions // and values bool requireThisSlot = false; foreach (CaseStatement.WhenThen clause in statement.Clauses) { clause.Condition.GetRequiredSlots(m_projectedSlotMap, requiredSlots); ProjectedSlot slot = clause.Value; if (!(slot is ConstantProjectedSlot)) { // If this slot is a scalar and a non-constant, // we need the lower down blocks to generate it for us requireThisSlot = true; } } EdmType edmType = caseMemberPath.EdmType; if (Helper.IsEntityType(edmType) || Helper.IsComplexType(edmType)) { foreach (EdmType instantiatedType in statement.InstantiatedTypes) { foreach (EdmMember childMember in Helper.GetAllStructuralMembers(instantiatedType)) { int slotNum = GetSlotIndex(caseMemberPath, childMember); requiredSlots[slotNum] = true; } } } else if (caseMemberPath.IsScalarType()) { // A scalar does not need anything per se to be constructed // unless it is referring to a field in the tree below, i.e., the THEN // slot is not a constant slot if (requireThisSlot) { int caseMemberSlotNum = m_projectedSlotMap.IndexOf(caseMemberPath); requiredSlots[caseMemberSlotNum] = true; } } else if (Helper.IsAssociationType(edmType)) { // For an association, get the indices of the ends, e.g., // CProduct and CCategory in CProductCategory1 // Need just it's ends AssociationSet associationSet = (AssociationSet)caseMemberPath.Extent; AssociationType associationType = associationSet.ElementType; foreach (AssociationEndMember endMember in associationType.AssociationEndMembers) { int slotNum = GetSlotIndex(caseMemberPath, endMember); requiredSlots[slotNum] = true; } } else { // For a reference, all we need are the keys RefType refType = edmType as RefType; Debug.Assert(refType != null, "What other non scalars do we have? Relation end must be a reference type"); EntityTypeBase refElementType = refType.ElementType; // Go through all the members of elementType and get the key properties EntitySet entitySet = MetadataHelper.GetEntitySetAtEnd((AssociationSet)caseMemberPath.Extent, (AssociationEndMember)caseMemberPath.LeafEdmMember); foreach (EdmMember entityMember in refElementType.KeyMembers) { int slotNum = GetSlotIndex(caseMemberPath, entityMember); requiredSlots[slotNum] = true; } } }
public ExplorerAssociationSet(EditingContext context, AssociationSet assocSet, ExplorerEFElement parent) : base(context, assocSet, parent) { // do nothing }
/// <summary> /// Returns true if this path and <paramref name="path1"/> are equivalent on the C-side via a referential constraint. /// </summary> internal bool IsEquivalentViaRefConstraint(MemberPath path1) { MemberPath path0 = this; // Now check if they are equivalent via referential constraint // For example, // * Person.pid and PersonAddress.Person.pid are equivalent // * Person.pid and PersonAddress.Address.pid are equivalent // * Person.pid and Address.pid are equivalent if there is a referential constraint // * PersonAddress.Person.pid and PersonAddress.Address.pid are // equivalent if there is a referential constraint // In short, Person.pid, Address.pid, PersonAddress.Address.pid, // PersonAddress.Person.pid are the same if (path0.EdmType is EntityTypeBase || path1.EdmType is EntityTypeBase || MetadataHelper.IsNonRefSimpleMember(path0.LeafEdmMember) == false || MetadataHelper.IsNonRefSimpleMember(path1.LeafEdmMember) == false) { // If the path corresponds to a top level extent only, ignore // it. Or if it is not a scalar return(false); } AssociationSet assocSet0 = path0.Extent as AssociationSet; AssociationSet assocSet1 = path1.Extent as AssociationSet; EntitySet entitySet0 = path0.Extent as EntitySet; EntitySet entitySet1 = path1.Extent as EntitySet; bool result = false; if (assocSet0 != null && assocSet1 != null) { // PersonAddress.Person.pid and PersonAddress.Address.pid case // Check if they are the same association or not if (assocSet0.Equals(assocSet1) == false) { return(false); } result = AreAssocationEndPathsEquivalentViaRefConstraint(path0, path1, assocSet0); } else if (entitySet0 != null && entitySet1 != null) { // Person.pid, Address.pid case // Find all the associations between the two sets. If the // fields are equivalent via any association + referential // constraint, return true List <AssociationSet> assocSets = MetadataHelper.GetAssociationsForEntitySets(entitySet0, entitySet1); foreach (AssociationSet assocSet in assocSets) { // For Person.pid, get PersonAddress.Person.pid or MemberPath assocEndPath0 = path0.GetCorrespondingAssociationPath(assocSet); MemberPath assocEndPath1 = path1.GetCorrespondingAssociationPath(assocSet); if (AreAssocationEndPathsEquivalentViaRefConstraint(assocEndPath0, assocEndPath1, assocSet)) { result = true; break; } } } else { // One of them is an assocSet and the other is an entity set AssociationSet assocSet = assocSet0 != null ? assocSet0 : assocSet1; EntitySet entitySet = entitySet0 != null ? entitySet0 : entitySet1; Debug.Assert(assocSet != null && entitySet != null, "One set must be association and the other must be entity set"); MemberPath assocEndPathA = path0.Extent is AssociationSet ? path0 : path1; MemberPath entityPath = path0.Extent is EntitySet ? path0 : path1; MemberPath assocEndPathB = entityPath.GetCorrespondingAssociationPath(assocSet); if (assocEndPathB == null) { //An EntitySet might participate in multiple AssociationSets //and this might not be the association set that defines the expected referential //constraint //Return false since this does not have any referential constraint specified result = false; } else { result = AreAssocationEndPathsEquivalentViaRefConstraint(assocEndPathA, assocEndPathB, assocSet); } } return(result); }
public IEntityWrapper HandleRelationshipSpan( IEntityWrapper wrappedEntity, EntityKey targetKey, AssociationEndMember targetMember) { if (wrappedEntity.Entity == null) { return(wrappedEntity); } EntityKey entityKey = wrappedEntity.EntityKey; AssociationEndMember otherAssociationEnd = MetadataHelper.GetOtherAssociationEnd(targetMember); this.CheckClearedEntryOnSpan((object)targetKey, wrappedEntity, entityKey, targetMember); if ((object)targetKey != null) { EntitySet endEntitySet; AssociationSet cspaceAssociationSet = this.Context.MetadataWorkspace.MetadataOptimization.FindCSpaceAssociationSet((AssociationType)targetMember.DeclaringType, targetMember.Name, targetKey.EntitySetName, targetKey.EntityContainerName, out endEntitySet); ObjectStateManager objectStateManager = this.Context.ObjectStateManager; EntityState newEntryState; if (!ObjectStateManager.TryUpdateExistingRelationships(this.Context, this.MergeOption, cspaceAssociationSet, otherAssociationEnd, entityKey, wrappedEntity, targetMember, targetKey, true, out newEntryState)) { EntityEntry entityEntry = objectStateManager.GetOrAddKeyEntry(targetKey, endEntitySet); bool flag = true; switch (otherAssociationEnd.RelationshipMultiplicity) { case RelationshipMultiplicity.ZeroOrOne: case RelationshipMultiplicity.One: flag = !ObjectStateManager.TryUpdateExistingRelationships(this.Context, this.MergeOption, cspaceAssociationSet, targetMember, targetKey, entityEntry.WrappedEntity, otherAssociationEnd, entityKey, true, out newEntryState); if (entityEntry.State == EntityState.Detached) { entityEntry = objectStateManager.AddKeyEntry(targetKey, endEntitySet); break; } break; } if (flag) { if (entityEntry.IsKeyEntry || newEntryState == EntityState.Deleted) { RelationshipWrapper wrapper = new RelationshipWrapper(cspaceAssociationSet, otherAssociationEnd.Name, entityKey, targetMember.Name, targetKey); objectStateManager.AddNewRelation(wrapper, newEntryState); } else if (entityEntry.State != EntityState.Deleted) { ObjectStateManager.AddEntityToCollectionOrReference(this.MergeOption, wrappedEntity, otherAssociationEnd, entityEntry.WrappedEntity, targetMember, true, false, false); } else { RelationshipWrapper wrapper = new RelationshipWrapper(cspaceAssociationSet, otherAssociationEnd.Name, entityKey, targetMember.Name, targetKey); objectStateManager.AddNewRelation(wrapper, EntityState.Deleted); } } } } else { RelatedEnd relatedEnd; if (this.TryGetRelatedEnd(wrappedEntity, (AssociationType)targetMember.DeclaringType, otherAssociationEnd.Name, targetMember.Name, out relatedEnd)) { this.SetIsLoadedForSpan(relatedEnd, false); } } return(wrappedEntity); }
// effects: Returns the entity set at the end corresponding to endMember internal static EntitySet GetEntitySetAtEnd( AssociationSet associationSet, AssociationEndMember endMember) { return(associationSet.AssociationSetEnds[endMember.Name].EntitySet); }
/// <summary> /// Initializes a new instance of the <see cref="AssociationSetData"/> class. /// </summary> /// <param name="parent">The parent entity container data.</param> /// <param name="associationSet">The association set.</param> internal AssociationSetData(EntityContainerData parent, AssociationSet associationSet) { this.Parent = parent; this.AssociationSet = associationSet; this.Rows = new List<AssociationSetDataRow>(); }
protected override void InvokeInternal(CommandProcessorContext cpc) { DesignerInfo designerInfo; Debug.Assert(cpc.Artifact != null, "Artifact was null"); if (Association != null && cpc.Artifact != null && cpc.Artifact.DesignerInfo() != null && cpc.Artifact.DesignerInfo().TryGetDesignerInfo(OptionsDesignerInfo.ElementName, out designerInfo)) { // APPDB_SCENARIO: We cannot use referential constraints for 0..1:0..1 or 1:1 associations, since these exist as configured // 0..1:* or 1:* associations and so introducing a referential constraint would cause validation errors. // Must use Referential Constraint for 1:0..1 relationship as using an AssociationSetMapping results in illegal reference to the same ID column twice (since the PK is also the FK) if (Association.IsOneToZeroOrOne || (UseReferentialConstraint && !(Association.IsZeroOrOneToZeroOrOne || Association.IsOneToOne))) { // We're including fk columns, so the update will consist of a ref constraint var createRefConCommand = new CreateOrUpdateReferentialConstraintCommand( (c, subCpc) => { var cmd = c as CreateOrUpdateReferentialConstraintCommand; cmd.PrincipalEnd = PrincipalEnd; cmd.DependentEnd = DependentEnd; cmd.PrincipalProperties = PrincipalProperties; cmd.DependentProperties = DependentProperties; return(cmd.PrincipalEnd != null && cmd.DependentEnd != null); }); CommandProcessor.InvokeSingleCommand(cpc, createRefConCommand); } else { // We're not including fk columns, so the update will consist of an association set mapping and a deletes of the fk columns (if they exist) // otherwise update AssociationSetMapping appropriately var createMapCommand = new CreateOrUpdateAssociationSetMappingCommand( (c, subCpc) => { var cmd = c as CreateOrUpdateAssociationSetMappingCommand; cmd.Association = Association; cmd.AssociationSet = AssociationSet; cmd.EntityContainerMapping = EntityContainerMapping; cmd.StorageEntitySet = StorageEntitySet; return(cmd.Association != null && cmd.AssociationSet != null && cmd.EntityContainerMapping != null && cmd.StorageEntitySet != null); }); CommandProcessor.InvokeSingleCommand(cpc, createMapCommand); // Delete the fk properties in the conceptual layer if they exist. Do not delete primary key properties though! if (!IncludeFkProperties) { var propertiesToDelete = DependentProperties.Where(p => p.EntityType != null && !p.EntityType.ResolvableKeys.Contains(p)).ToList(); foreach (var p in propertiesToDelete) { var deletePropertyCmd = new DeletePropertyCommand( (c, subCpc) => { var cmd = c as DeletePropertyCommand; cmd.EFElement = p; return(cmd.EFElement != null); }); CommandProcessor.InvokeSingleCommand(cpc, deletePropertyCmd); } } // Add or update the EndProperty elements for the AssociationSetMapping. Try to work out which end is the principal // end by looking at the multiplicity, since we don't have a referential constraint in this case. AssociationSetEnd principalSetEnd; AssociationSetEnd dependentSetEnd; Debug.Assert( AssociationSet.AssociationSetEnds().First().Role.Target != null, "Role Target for Association End was null, AssociationSetMapping update failed"); if (AssociationSet.AssociationSetEnds().First().Role.Target != null) { if (Association.End1.Multiplicity.Value == ModelConstants.Multiplicity_Many) { principalSetEnd = AssociationSet.AssociationSetEnds().Last(); dependentSetEnd = AssociationSet.AssociationSetEnds().First(); } else { principalSetEnd = AssociationSet.AssociationSetEnds().First(); dependentSetEnd = AssociationSet.AssociationSetEnds().Last(); } var dependentEndPropertyCmd = new CreateOrUpdateEndPropertyCommand( (c, subCpc) => { var cmd = c as CreateOrUpdateEndPropertyCommand; cmd.AssociationSetEnd = dependentSetEnd; cmd.AssociationSetMapping = createMapCommand.AssociationSetMapping; cmd.StorageKeyProperties = StorageDependentTypeKeyProperties; cmd.ConceptualKeyProperties = ConceptualDependentType.SafeInheritedAndDeclaredProperties.Where(p => p.IsKeyProperty); return(cmd.AssociationSetEnd != null && cmd.AssociationSetMapping != null); }); var principalEndPropertyCmd = new CreateOrUpdateEndPropertyCommand( (c, subCpc) => { var cmd = c as CreateOrUpdateEndPropertyCommand; cmd.AssociationSetEnd = principalSetEnd; cmd.AssociationSetMapping = createMapCommand.AssociationSetMapping; cmd.StorageKeyProperties = StorageDependentTypeForeignKeyProperties; cmd.ConceptualKeyProperties = ConceptualPrincipalType.SafeInheritedAndDeclaredProperties.Where(p => p.IsKeyProperty); return(cmd.AssociationSetEnd != null && cmd.AssociationSetMapping != null); }); CommandProcessor.InvokeSingleCommand(cpc, dependentEndPropertyCmd); CommandProcessor.InvokeSingleCommand(cpc, principalEndPropertyCmd); } } } }
private static void AddNavigationProperties( AssociationSet efAssociationSet, IDictionary <MetadataItem, IEdmElement> elementMap) { if (efAssociationSet.AssociationSetEnds.Count != 2) { return; } var efAssociation = efAssociationSet.ElementType; var navPropertyInfos = new EdmNavigationPropertyInfo[2]; for (var i = 0; i < 2; i++) { var efEnd = efAssociation.AssociationEndMembers[i]; var efEntityType = efEnd.GetEntityType(); if (!elementMap.ContainsKey(efEntityType)) { continue; } var entityType = elementMap[efEntityType] as IEdmEntityType; var efNavProperty = efEntityType.NavigationProperties .Where(np => np.FromEndMember == efEnd) .SingleOrDefault(); if (efNavProperty == null) { continue; } var efTargetEntityType = efNavProperty .ToEndMember.GetEntityType(); if (!elementMap.ContainsKey(efTargetEntityType)) { continue; } var targetEntityType = elementMap[efTargetEntityType] as IEdmEntityType; navPropertyInfos[i] = new EdmNavigationPropertyInfo() { ContainsTarget = false, Name = efNavProperty.Name, OnDelete = efEnd.DeleteBehavior == OperationAction.Cascade ? EdmOnDeleteAction.Cascade : EdmOnDeleteAction.None, Target = targetEntityType, TargetMultiplicity = GetEdmMultiplicity( efNavProperty.ToEndMember.RelationshipMultiplicity) }; var constraint = efAssociation.Constraint; if (constraint != null && constraint.ToRole == efEnd) { navPropertyInfos[i].DependentProperties = constraint.ToProperties .Select(p => entityType.FindProperty(p.Name) as IEdmStructuralProperty); navPropertyInfos[i].PrincipalProperties = constraint.FromProperties .Select(p => targetEntityType.FindProperty(p.Name) as IEdmStructuralProperty); } } if (navPropertyInfos[0] == null && navPropertyInfos[1] != null) { var efEnd = efAssociation.AssociationEndMembers[1]; var efEntityType = efEnd.GetEntityType(); var entityType = elementMap[efEntityType] as EdmEntityType; if (entityType.FindProperty(navPropertyInfos[1].Name) == null) { entityType.AddUnidirectionalNavigation(navPropertyInfos[1]); } } if (navPropertyInfos[0] != null && navPropertyInfos[1] == null) { var efEnd = efAssociation.AssociationEndMembers[0]; var efEntityType = efEnd.GetEntityType(); var entityType = elementMap[efEntityType] as EdmEntityType; if (entityType.FindProperty(navPropertyInfos[0].Name) == null) { entityType.AddUnidirectionalNavigation(navPropertyInfos[0]); } } if (navPropertyInfos[0] != null && navPropertyInfos[1] != null) { var efEnd = efAssociation.AssociationEndMembers[0]; var efEntityType = efEnd.GetEntityType(); var entityType = elementMap[efEntityType] as EdmEntityType; if (entityType.FindProperty(navPropertyInfos[0].Name) == null) { entityType.AddBidirectionalNavigation( navPropertyInfos[0], navPropertyInfos[1]); } } }
/// <summary> /// Initializes a new instance of the <see cref="AssociationSetData"/> class. /// </summary> /// <param name="parent">The parent entity container data.</param> /// <param name="associationSet">The association set.</param> internal AssociationSetData(EntityContainerData parent, AssociationSet associationSet) { this.Parent = parent; this.AssociationSet = associationSet; this.Rows = new List <AssociationSetDataRow>(); }
/// <summary> /// Gets information relevant to the processing of an AssociationSet in the update pipeline. /// Caches information on first retrieval. /// </summary> internal AssociationSetMetadata GetAssociationSetMetadata(AssociationSet associationSet, MetadataWorkspace workspace) { return(SyncGetValue(associationSet, workspace, m_associationSetMetadata, associationSet)); }
public void WriteAssociationSetMapping_should_write_modification_function_mapping() { var fixture = new Fixture(); var entityType = new EntityType("E", "N", DataSpace.CSpace); var entitySet = new EntitySet("ES", "S", null, null, entityType); new EntityContainer("EC", DataSpace.SSpace).AddEntitySetBase(entitySet); var associationSet = new AssociationSet("AS", new AssociationType("A", XmlConstants.ModelNamespace_3, false, DataSpace.CSpace)); var associationEndMember1 = new AssociationEndMember("Source", new EntityType("E", "N", DataSpace.CSpace)); associationSet.AddAssociationSetEnd(new AssociationSetEnd(entitySet, associationSet, associationEndMember1)); var associationEndMember2 = new AssociationEndMember("Target", new EntityType("E", "N", DataSpace.CSpace)); associationSet.AddAssociationSetEnd(new AssociationSetEnd(entitySet, associationSet, associationEndMember2)); var storageModificationFunctionMapping = new StorageModificationFunctionMapping( associationSet, associationSet.ElementType, new EdmFunction("F", "N", DataSpace.SSpace, new EdmFunctionPayload()), new[] { new StorageModificationFunctionParameterBinding( new FunctionParameter( "P", TypeUsage.Create(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32)), ParameterMode.In), new StorageModificationFunctionMemberPath( new EdmMember[] { new EdmProperty("K"), associationEndMember1 }, associationSet), true), new StorageModificationFunctionParameterBinding( new FunctionParameter( "P", TypeUsage.Create(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32)), ParameterMode.In), new StorageModificationFunctionMemberPath( new EdmMember[] { new EdmProperty("K"), associationEndMember2 }, associationSet), false) }, null, null); var associationSetMapping = new StorageAssociationSetMapping( associationSet, entitySet) { SourceEndMapping = new StorageEndPropertyMapping { EndMember = associationEndMember1 }, TargetEndMapping = new StorageEndPropertyMapping { EndMember = associationEndMember2 }, ModificationFunctionMapping = new StorageAssociationSetModificationFunctionMapping( associationSet, storageModificationFunctionMapping, storageModificationFunctionMapping) }; fixture.Writer.WriteAssociationSetMappingElement(associationSetMapping); Assert.Equal( @"<AssociationSetMapping Name=""AS"" TypeName="".A"" StoreEntitySet=""E""> <EndProperty Name=""Source"" /> <EndProperty Name=""Target"" /> <ModificationFunctionMapping> <InsertFunction FunctionName=""N.F""> <EndProperty Name=""Source""> <ScalarProperty Name=""K"" ParameterName=""P"" Version=""Current"" /> </EndProperty> <EndProperty Name=""Target""> <ScalarProperty Name=""K"" ParameterName=""P"" Version=""Original"" /> </EndProperty> </InsertFunction> <DeleteFunction FunctionName=""N.F""> <EndProperty Name=""Source""> <ScalarProperty Name=""K"" ParameterName=""P"" Version=""Current"" /> </EndProperty> <EndProperty Name=""Target""> <ScalarProperty Name=""K"" ParameterName=""P"" Version=""Original"" /> </EndProperty> </DeleteFunction> </ModificationFunctionMapping> </AssociationSetMapping>", fixture.ToString()); }
public void BuildAssociationSetMappings_builds_conceptual_assocation_set_mapping_for_collapsed_store_entity_sets() { #region Setting up many to many relationship in the SSpace Teacher * -- 1 TeacherStudents 1 -- * Teachers var joinStoreEntityType = EntityType.Create( "TeacherStudents", "ns.Store", DataSpace.SSpace, new[] { "JoinTeacherId", "JoinStudentId" }, new[] { CreateStoreProperty("JoinTeacherId", "int"), CreateStoreProperty("JoinStudentId", "int") }, null); var joinStoreEntitySet = EntitySet.Create("TeacherStudentsSet", "dbo", "TeacherStudentTable", null, joinStoreEntityType, null); var storeTeacherEntityType = EntityType.Create( "Teacher", "ns.Store", DataSpace.SSpace, new[] { "TeacherId" }, new[] { CreateStoreProperty("TeacherId", "int") }, null); var storeTeacherEntitySet = EntitySet.Create("TeachersSet", "dbo", "Teachers", null, storeTeacherEntityType, null); var storeStudentEntityType = EntityType.Create( "Student", "ns.Store", DataSpace.SSpace, new[] { "StudentId" }, new[] { CreateStoreProperty("StudentId", "int") }, null); var storeStudentEntitySet = EntitySet.Create("StudentSet", "dbo", "Students", null, storeStudentEntityType, null); var storeTeachersEndMember = AssociationEndMember.Create( "Teachers", storeTeacherEntityType.GetReferenceType(), RelationshipMultiplicity.Many, OperationAction.None, null); var storeTeacherStudentsfromTeachersEndMember = AssociationEndMember.Create( "TeacherStudents_fromTeachers", joinStoreEntityType.GetReferenceType(), RelationshipMultiplicity.One, OperationAction.None, null); var storeTeacherAssociationType = AssociationType.Create( "Teacher_TeacherStudentsAssociationType", "ns.Store", false, DataSpace.SSpace, storeTeachersEndMember, storeTeacherStudentsfromTeachersEndMember, new ReferentialConstraint( storeTeachersEndMember, storeTeacherStudentsfromTeachersEndMember, storeTeacherEntityType.KeyProperties, joinStoreEntityType.KeyProperties.Where(p => p.Name == "JoinTeacherId")), null); var storeTeacherAssociationSet = AssociationSet.Create( "Teacher_TeacherStudents", storeTeacherAssociationType, storeTeacherEntitySet, joinStoreEntitySet, null); var storeStudentsEndMember = AssociationEndMember.Create( "Students", storeStudentEntityType.GetReferenceType(), RelationshipMultiplicity.Many, OperationAction.None, null); var storeTeacherStudentsfromStudentsEndMember = AssociationEndMember.Create( "TeacherStudents_fromStudents", joinStoreEntityType.GetReferenceType(), RelationshipMultiplicity.One, OperationAction.None, null); var storeStudentAssociationType = AssociationType.Create( "Student_TeacherStudentsAssociationType", "ns.Store", false, DataSpace.SSpace, storeStudentsEndMember, storeTeacherStudentsfromStudentsEndMember, new ReferentialConstraint( storeStudentsEndMember, storeTeacherStudentsfromStudentsEndMember, storeStudentEntityType.KeyProperties, joinStoreEntityType.KeyProperties.Where(p => p.Name == "JoinStudentId")), null); var storeStudentAssociationSet = AssociationSet.Create( "Student_TeacherStudents", storeStudentAssociationType, storeStudentEntitySet, joinStoreEntitySet, null); var collapsedAssociationSet = new CollapsibleEntityAssociationSets(joinStoreEntitySet); collapsedAssociationSet.AssociationSets.Add(storeTeacherAssociationSet); collapsedAssociationSet.AssociationSets.Add(storeStudentAssociationSet); #endregion #region Setting up many to many relationship in the CSpace Teacher * -- * Teachers var conceptualContainer = EntityContainer.Create("ConceptualContainer", DataSpace.CSpace, null, null, null); var edmIntTypeUsage = TypeUsage.CreateDefaultTypeUsage(PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32)); var conceptualTeacherEntityType = EntityType.Create( "Teacher", "ns", DataSpace.CSpace, new[] { "TeacherId" }, new[] { EdmProperty.Create("TeacherId", edmIntTypeUsage) }, null); var conceptualTeacherEntitySet = EntitySet.Create("TeachersSet", null, null, null, conceptualTeacherEntityType, null); var conceptualStudentEntityType = EntityType.Create( "Student", "ns", DataSpace.CSpace, new[] { "StudentId" }, new[] { EdmProperty.Create("StudentId", edmIntTypeUsage) }, null); var conceptualStudentEntitySet = EntitySet.Create("StudentSet", "dbo", "Students", null, conceptualStudentEntityType, null); var conceptualTeachersEndMember = AssociationEndMember.Create( "TeachersEnd", conceptualTeacherEntityType.GetReferenceType(), RelationshipMultiplicity.Many, OperationAction.None, null); var conceptualStudentsEndMember = AssociationEndMember.Create( "StudentsEnd", conceptualStudentEntityType.GetReferenceType(), RelationshipMultiplicity.Many, OperationAction.None, null); var conceptualAssociationType = AssociationType.Create( "TeacherStudentAssociation", "ns.Model", false, DataSpace.CSpace, conceptualTeachersEndMember, conceptualStudentsEndMember, new ReferentialConstraint( conceptualTeachersEndMember, conceptualStudentsEndMember, conceptualTeacherEntityType.KeyProperties, conceptualStudentEntityType.KeyProperties), null); var conceptualAssociationSet = AssociationSet.Create( "TeacherStudentSet", conceptualAssociationType, conceptualTeacherEntitySet, conceptualStudentEntitySet, null); #endregion var mappingContext = new SimpleMappingContext(new EdmModel(DataSpace.SSpace), true); mappingContext.AddMapping(collapsedAssociationSet, conceptualAssociationSet); mappingContext.AddMapping(storeTeachersEndMember, conceptualTeachersEndMember); mappingContext.AddMapping(storeStudentsEndMember, conceptualStudentsEndMember); mappingContext.AddMapping( storeTeacherAssociationSet.AssociationSetEnds.ElementAt(0), conceptualAssociationSet.AssociationSetEnds.ElementAt(0)); mappingContext.AddMapping( storeStudentAssociationSet.AssociationSetEnds.ElementAt(0), conceptualAssociationSet.AssociationSetEnds.ElementAt(1)); mappingContext.AddMapping( storeStudentEntityType.KeyProperties.Single(), conceptualStudentEntityType.KeyProperties.Single()); mappingContext.AddMapping( storeTeacherEntityType.KeyProperties.Single(), conceptualTeacherEntityType.KeyProperties.Single()); var storageEntitySetMapping = new EntityContainerMapping(conceptualContainer, null, null, false, false); var associationSetMapping = DbDatabaseMappingBuilder.BuildAssociationSetMappings(storageEntitySetMapping, mappingContext) .SingleOrDefault(); Assert.NotNull(associationSetMapping); var mappingFragment = associationSetMapping.TypeMappings.SingleOrDefault(); Assert.NotNull(mappingFragment); var propertyMappings = mappingFragment.MappingFragments.Single().PropertyMappings; Assert.Equal(2, propertyMappings.Count); Assert.Same(conceptualTeachersEndMember, ((EndPropertyMapping)propertyMappings[0]).AssociationEnd); Assert.Same(conceptualStudentsEndMember, ((EndPropertyMapping)propertyMappings[1]).AssociationEnd); var scalarPropertyMapping = ((EndPropertyMapping)propertyMappings[0]).PropertyMappings.Single(); Assert.Same(conceptualTeacherEntityType.KeyMembers.Single(), scalarPropertyMapping.Property); Assert.Same( joinStoreEntityType.KeyMembers.Single(m => m.Name == "JoinTeacherId"), scalarPropertyMapping.Column); scalarPropertyMapping = ((EndPropertyMapping)propertyMappings[1]).PropertyMappings.Single(); Assert.Same(conceptualStudentEntityType.KeyMembers.Single(), scalarPropertyMapping.Property); Assert.Same( joinStoreEntityType.KeyMembers.Single(m => m.Name == "JoinStudentId"), scalarPropertyMapping.Column); }
internal void CreateAssociationConstraints(EntitySetBase extent, MemberDomainMap domainMap, EdmItemCollection edmItemCollection) { AssociationSet assocSet = extent as AssociationSet; if (assocSet != null) { BoolExpression assocSetExpr = BoolExpression.CreateLiteral(new RoleBoolean(assocSet), domainMap); //Set of Keys for this Association Set //need to key on EdmMember and EdmType because A, B subtype of C, can have the same id (EdmMember) that is defined in C. HashSet <Pair <EdmMember, EntityType> > associationkeys = new HashSet <Pair <EdmMember, EntityType> >(); //foreach end, add each Key foreach (var endMember in assocSet.ElementType.AssociationEndMembers) { EntityType type = (EntityType)((RefType)endMember.TypeUsage.EdmType).ElementType; type.KeyMembers.All(member => associationkeys.Add(new Pair <EdmMember, EntityType>(member, type)) || true /* prevent early termination */); } foreach (AssociationSetEnd end in assocSet.AssociationSetEnds) { // construct type condition HashSet <EdmType> derivedTypes = new HashSet <EdmType>(); derivedTypes.UnionWith(MetadataHelper.GetTypeAndSubtypesOf(end.CorrespondingAssociationEndMember.TypeUsage.EdmType, edmItemCollection, false)); BoolExpression typeCondition = CreateIsOfTypeCondition(new MemberPath(end.EntitySet), derivedTypes, domainMap); BoolExpression inRoleExpression = BoolExpression.CreateLiteral(new RoleBoolean(end), domainMap); BoolExpression inSetExpression = BoolExpression.CreateAnd( BoolExpression.CreateLiteral(new RoleBoolean(end.EntitySet), domainMap), typeCondition); // InRole -> (InSet AND type(Set)=T) AddImplication(inRoleExpression.Tree, inSetExpression.Tree); if (MetadataHelper.IsEveryOtherEndAtLeastOne(assocSet, end.CorrespondingAssociationEndMember)) { AddImplication(inSetExpression.Tree, inRoleExpression.Tree); } // Add equivalence between association set an End/Role if necessary. // Equivalence is added when a given association end's keys subsumes keys for // all the other association end. // For example: We have Entity Sets A[id1], B[id2, id3] and an association A_B between them. // Ref Constraint A.id1 = B.id2 // In this case, the Association Set has Key <id1, id2, id3> // id1 alone can not identify a unique tuple in the Association Set, but <id2, id3> can. // Therefore we add a constraint: InSet(B) <=> InEnd(A_B.B) if (MetadataHelper.DoesEndKeySubsumeAssociationSetKey(assocSet, end.CorrespondingAssociationEndMember, associationkeys)) { AddEquivalence(inRoleExpression.Tree, assocSetExpr.Tree); } } // add rules for referential constraints (borrowed from LeftCellWrapper.cs) AssociationType assocType = assocSet.ElementType; foreach (ReferentialConstraint constraint in assocType.ReferentialConstraints) { AssociationEndMember toEndMember = (AssociationEndMember)constraint.ToRole; EntitySet toEntitySet = MetadataHelper.GetEntitySetAtEnd(assocSet, toEndMember); // Check if the keys of the entitySet's are equal to what is specified in the constraint // How annoying that KeyMembers returns EdmMember and not EdmProperty IEnumerable <EdmMember> toProperties = Helpers.AsSuperTypeList <EdmProperty, EdmMember>(constraint.ToProperties); if (Helpers.IsSetEqual(toProperties, toEntitySet.ElementType.KeyMembers, EqualityComparer <EdmMember> .Default)) { // Now check that the FromEnd is 1..1 (only then will all the Addresses be present in the assoc set) if (constraint.FromRole.RelationshipMultiplicity.Equals(RelationshipMultiplicity.One)) { // Make sure that the ToEnd is not 0..* because then the schema is broken Debug.Assert(constraint.ToRole.RelationshipMultiplicity.Equals(RelationshipMultiplicity.Many) == false); // Equate the ends BoolExpression inRoleExpression1 = BoolExpression.CreateLiteral(new RoleBoolean(assocSet.AssociationSetEnds[0]), domainMap); BoolExpression inRoleExpression2 = BoolExpression.CreateLiteral(new RoleBoolean(assocSet.AssociationSetEnds[1]), domainMap); AddEquivalence(inRoleExpression1.Tree, inRoleExpression2.Tree); } } } } }
/// <summary> /// check whether the EntityContainerMapping contains /// the map for the given AssociationSet /// </summary> /// <param name="associationSet"></param> /// <returns></returns> internal bool ContainsAssociationSetMapping(AssociationSet associationSet) { return(this.m_associationSetMappings.ContainsKey(associationSet.Name)); }
private void PopulateNavigateResult(EntitySetDataRow row, QueryEntityValue entityInstance, AssociationSet associationSet, AssociationSetEnd fromSetEnd, AssociationSetEnd toSetEnd) { EntityContainerData containerData = row.Parent.Parent; var associationSetData = containerData.GetAssociationSetData(associationSet.Name); var targetInstanceLookup = this.rowInstances[toSetEnd.EntitySet.Name]; var associatedObjects = associationSetData.Rows .Where(r => r.GetRoleKey(fromSetEnd.AssociationEnd.RoleName).Equals(row.Key)) .Select(r => targetInstanceLookup[r.GetRoleKey(toSetEnd.AssociationEnd.RoleName)]) .ToArray(); var toEntityType = toSetEnd.AssociationEnd.EntityType; var toQueryEntityType = this.GetQueryType(toSetEnd.EntitySet.Name, toEntityType); if (toSetEnd.AssociationEnd.Multiplicity == EndMultiplicity.Many) { var collectionType = toQueryEntityType.CreateCollectionType(); var collectionValue = collectionType.CreateCollectionWithValues(associatedObjects); entityInstance.SetNavigateResult(associationSet.AssociationType, toSetEnd.AssociationEnd, collectionValue); } else { if (associatedObjects.Length == 0) { entityInstance.SetNavigateResult(associationSet.AssociationType, toSetEnd.AssociationEnd, toQueryEntityType.NullValue); } else { if (associatedObjects.Length != 1) { var debugAssociatedValues = string.Join("," + Environment.NewLine, associatedObjects.Select(ao => ao.ToString())); throw new TaupoInfrastructureException( string.Format( CultureInfo.InvariantCulture, "Found {0} associated objects for {1}.{2}, on Entity Instance {3} associated Objects = {4}", associatedObjects.Length, associationSet.AssociationType.FullName, fromSetEnd.AssociationEnd.RoleName, entityInstance, debugAssociatedValues)); } var targetInstance = associatedObjects.Single(); entityInstance.SetNavigateResult(associationSet.AssociationType, toSetEnd.AssociationEnd, targetInstance); } } }
protected override void VisitEdmAssociationSet(AssociationSet item) { Dispatch(item); base.VisitEdmAssociationSet(item); }
private void WriteAssociationSetMappingElement(XmlWriter writer, AssociationSet store, AssociationSet model) { if (!model.ElementType.IsForeignKey) { writer.WriteStartElement(StorageMslConstructs.AssociationSetMappingElement, _xmlNamespace); writer.WriteAttributeString(StorageMslConstructs.AssociationSetMappingNameAttribute, model.Name); writer.WriteAttributeString(StorageMslConstructs.AssociationSetMappingTypeNameAttribute, model.ElementType.FullName); // all column names must be the primary key of the // end, but as columns in the Fk table. AssociationSetEnd foreignKeyTableEnd = GetAssociationSetEndForForeignKeyTable(store); writer.WriteAttributeString(StorageMslConstructs.AssociationSetMappingStoreEntitySetAttribute, foreignKeyTableEnd.EntitySet.Name); foreach (AssociationSetEnd storeEnd in store.AssociationSetEnds) { AssociationSetEnd modelEnd = _lookups.StoreAssociationSetEndToModelAssociationSetEnd[storeEnd]; WriteEndPropertyElement(writer, storeEnd, modelEnd); } ReferentialConstraint constraint = GetReferentialConstraint(store); foreach (EdmProperty fkColumn in constraint.ToProperties) { if (fkColumn.Nullable) { WriteConditionElement(writer, fkColumn); } } writer.WriteEndElement(); } }
// effects: Given a container, ensures that all entity/association // sets in container on the C-side have been mapped private static ErrorLog EnsureAllCSpaceContainerSetsAreMapped(IEnumerable <Cell> cells, ConfigViewGenerator config, StorageEntityContainerMapping containerMapping) { Set <EntitySetBase> mappedExtents = new Set <EntitySetBase>(); string mslFileLocation = null; EntityContainer container = null; // Determine the container and name of the file while determining // the set of mapped extents in the cells foreach (Cell cell in cells) { mappedExtents.Add(cell.CQuery.Extent); mslFileLocation = cell.CellLabel.SourceLocation; // All cells are from the same container container = cell.CQuery.Extent.EntityContainer; } Debug.Assert(container != null); List <EntitySetBase> missingExtents = new List <EntitySetBase>(); // Go through all the extents in the container and determine // extents that are missing foreach (EntitySetBase extent in container.BaseEntitySets) { if (mappedExtents.Contains(extent) == false && !(containerMapping.HasQueryViewForSetMap(extent.Name))) { AssociationSet associationSet = extent as AssociationSet; if (associationSet == null || !associationSet.ElementType.IsForeignKey) { missingExtents.Add(extent); } } } ErrorLog errorLog = new ErrorLog(); // If any extent is not mapped, add an error if (missingExtents.Count > 0) { StringBuilder extentBuilder = new StringBuilder(); bool isFirst = true; foreach (EntitySetBase extent in missingExtents) { if (isFirst == false) { extentBuilder.Append(", "); } isFirst = false; extentBuilder.Append(extent.Name); } string message = System.Data.Entity.Strings.ViewGen_Missing_Set_Mapping(extentBuilder); // Find the cell with smallest line number - so that we can // point to the beginning of the file int lowestLineNum = -1; Cell smallestCell = null; foreach (Cell cell in cells) { if (lowestLineNum == -1 || cell.CellLabel.StartLineNumber < lowestLineNum) { smallestCell = cell; lowestLineNum = cell.CellLabel.StartLineNumber; } } Debug.Assert(smallestCell != null && lowestLineNum >= 0); EdmSchemaError edmSchemaError = new EdmSchemaError(message, (int)ViewGenErrorCode.MissingExtentMapping, EdmSchemaErrorSeverity.Error, containerMapping.SourceLocation, containerMapping.StartLineNumber, containerMapping.StartLinePosition, null); ErrorLog.Record record = new ErrorLog.Record(edmSchemaError); errorLog.AddEntry(record); } return(errorLog); }
private static AssociationSetEnd GetAssociationSetEndForForeignKeyTable(AssociationSet store) { ReferentialConstraint constraint = GetReferentialConstraint(store); return(store.AssociationSetEnds.GetValue(constraint.ToRole.Name, false)); }
private static ReferentialConstraint GetReferentialConstraint(AssociationSet associationSet) { Debug.Assert(associationSet.ElementType.ReferentialConstraints.Count == 1); return(associationSet.ElementType.ReferentialConstraints[0]); }
/// <summary> /// Construct a new AssociationSetMapping object /// </summary> /// <param name="extent"> Represents the Association Set Metadata object. Will change this to Extent instead of MemberMetadata. </param> /// <param name="entityContainerMapping"> The entityContainerMapping mapping that contains this Set mapping </param> public StorageAssociationSetMapping(AssociationSet extent, StorageEntityContainerMapping entityContainerMapping) : base(extent, entityContainerMapping) { }
/// <summary> /// Initializes a new instance of AssocationSetEnd /// </summary> /// <param name="entitySet">Entity set that this end refers to</param> /// <param name="parentSet">The association set which this belongs to</param> /// <param name="endMember">The end member of the association set which this is an instance of</param> /// <exception cref="System.ArgumentNullException">Thrown if either the role,entitySet, parentSet or endMember arguments are null </exception> internal AssociationSetEnd(EntitySet entitySet, AssociationSet parentSet, AssociationEndMember endMember) { _entitySet = EntityUtil.GenericCheckArgumentNull(entitySet, "entitySet"); _parentSet = EntityUtil.GenericCheckArgumentNull(parentSet, "parentSet"); _endMember = EntityUtil.GenericCheckArgumentNull(endMember, "endMember"); }
private void GenerateAssociationSet( SimpleMappingContext mappingContext, CollapsibleEntityAssociationSets collapsibleItem, UniqueIdentifierService uniqueEntityContainerNames, UniqueIdentifierService globallyUniqueTypeNames) { var uniqueEndMemberNames = new UniqueIdentifierService(StringComparer.OrdinalIgnoreCase); var associationSetEndDetails0 = collapsibleItem.GetStoreAssociationSetEnd(0); var associationEndMember0 = GenerateAssociationEndMember( mappingContext, associationSetEndDetails0.AssociationSetEnd.CorrespondingAssociationEndMember, uniqueEndMemberNames, associationSetEndDetails0.Multiplicity, associationSetEndDetails0.DeleteBehavior); var conceptualEntitySet0 = mappingContext[associationSetEndDetails0.AssociationSetEnd.EntitySet]; var associationSetEndDetails1 = collapsibleItem.GetStoreAssociationSetEnd(1); var associationEndMember1 = GenerateAssociationEndMember( mappingContext, associationSetEndDetails1.AssociationSetEnd.CorrespondingAssociationEndMember, uniqueEndMemberNames, associationSetEndDetails1.Multiplicity, associationSetEndDetails1.DeleteBehavior); var conceptualEntitySet1 = mappingContext[associationSetEndDetails1.AssociationSetEnd.EntitySet]; globallyUniqueTypeNames.UnregisterIdentifier(mappingContext[collapsibleItem.EntitySet.ElementType].Name); uniqueEntityContainerNames.UnregisterIdentifier(mappingContext[collapsibleItem.EntitySet].Name); var associationTypeName = CreateModelName(collapsibleItem.EntitySet.Name, globallyUniqueTypeNames); var associationSetName = CreateModelName(collapsibleItem.EntitySet.Name, uniqueEntityContainerNames); var conceptualAssociationType = AssociationType.Create( associationTypeName, _namespaceName, false, DataSpace.CSpace, associationEndMember0, associationEndMember1, null, // Don't need a referential constraint. null); CreateModelNavigationProperties(conceptualAssociationType); var conceptualAssociationSet = AssociationSet.Create( associationSetName, conceptualAssociationType, conceptualEntitySet0, conceptualEntitySet1, null); Debug.Assert(conceptualAssociationSet.AssociationSetEnds.Count == 2); var conceptualSetEnd0 = conceptualAssociationSet.AssociationSetEnds[0]; var conceptualSetEnd1 = conceptualAssociationSet.AssociationSetEnds[1]; mappingContext.AddMapping(associationSetEndDetails0.AssociationSetEnd, conceptualSetEnd0); mappingContext.AddMapping(associationSetEndDetails1.AssociationSetEnd, conceptualSetEnd1); mappingContext.AddMapping(collapsibleItem, conceptualAssociationSet); mappingContext.RemoveMapping(collapsibleItem.EntitySet); }
public override string WriteDropForeignKey(AssociationSet associationSet) { return(string.Empty); }
private IEnumerable <XElement> GenerateAssociationSetEnds(XNamespace xmlNamespace, AssociationSet associationSet) { var content = from setEnd in associationSet.Ends select this.GenerateAssociationSetEnd(xmlNamespace, setEnd); return(content); }
// Loads and registers any function mapping translators for the given extent (and related container) private void InitializeFunctionMappingTranslators(EntitySetBase entitySetBase, StorageEntityContainerMapping mapping) { KeyToListMap <AssociationSet, AssociationEndMember> requiredEnds = new KeyToListMap <AssociationSet, AssociationEndMember>( EqualityComparer <AssociationSet> .Default); // see if function mapping metadata needs to be processed if (!m_functionMappingTranslators.ContainsKey(entitySetBase)) { // load all function mapping data from the current entity container foreach (StorageEntitySetMapping entitySetMapping in mapping.EntitySetMaps) { if (0 < entitySetMapping.ModificationFunctionMappings.Count) { // register the function mapping m_functionMappingTranslators.Add(entitySetMapping.Set, ModificationFunctionMappingTranslator.CreateEntitySetTranslator(entitySetMapping)); // register "null" function translators for all implicitly mapped association sets foreach (AssociationSetEnd end in entitySetMapping.ImplicitlyMappedAssociationSetEnds) { AssociationSet associationSet = end.ParentAssociationSet; if (!m_functionMappingTranslators.ContainsKey(associationSet)) { m_functionMappingTranslators.Add(associationSet, ModificationFunctionMappingTranslator.CreateAssociationSetTranslator(null)); } // Remember that the current entity set is required for all updates to the collocated // relationship set. This entity set's end is opposite the target end for the mapping. AssociationSetEnd oppositeEnd = MetadataHelper.GetOppositeEnd(end); requiredEnds.Add(associationSet, oppositeEnd.CorrespondingAssociationEndMember); } } else { // register null translator (so that we never attempt to process this extent again) m_functionMappingTranslators.Add(entitySetMapping.Set, null); } } foreach (StorageAssociationSetMapping associationSetMapping in mapping.RelationshipSetMaps) { if (null != associationSetMapping.ModificationFunctionMapping) { AssociationSet set = (AssociationSet)associationSetMapping.Set; // use indexer rather than Add since the association set may already have an implicit function // mapping -- this explicit function mapping takes precedence in such cases m_functionMappingTranslators.Add(set, ModificationFunctionMappingTranslator.CreateAssociationSetTranslator(associationSetMapping)); // remember that we've seen a function mapping for this association set, which overrides // any other behaviors for determining required/optional ends requiredEnds.AddRange(set, Enumerable.Empty <AssociationEndMember>()); } else { if (!m_functionMappingTranslators.ContainsKey(associationSetMapping.Set)) { // register null translator (so that we never attempt to process this extent again) m_functionMappingTranslators.Add(associationSetMapping.Set, null); } } } } // register association metadata for all association sets encountered foreach (AssociationSet associationSet in requiredEnds.Keys) { m_associationSetMetadata.Add(associationSet, new AssociationSetMetadata( requiredEnds.EnumerateValues(associationSet))); } }
internal StorageModificationFunctionMemberPath(IEnumerable <EdmMember> members, AssociationSet associationSetNavigation) { this.Members = new ReadOnlyCollection <EdmMember>(new List <EdmMember>( EntityUtil.CheckArgumentNull(members, "members"))); if (null != associationSetNavigation) { Debug.Assert(2 == this.Members.Count, "Association bindings must always consist of the end and the key"); // find the association set end this.AssociationSetEnd = associationSetNavigation.AssociationSetEnds[this.Members[1].Name]; } }
private string GetTable( AssociationSet association, RelationshipEndMember relationEndpoint) { RefType refType = relationEndpoint.TypeUsage.EdmType as RefType; return association .AssociationSetEnds .Select(x => x.EntitySet) .First(x => x.ElementType == refType.ElementType) .GetTableName(); }
internal DirectionalRelationship(EntityKey toEntityKey, AssociationEndMember fromEnd, AssociationEndMember toEnd, AssociationSet associationSet, IEntityStateEntry stateEntry) { ToEntityKey = EntityUtil.CheckArgumentNull(toEntityKey, "toEntityKey"); FromEnd = EntityUtil.CheckArgumentNull(fromEnd, "fromEnd"); ToEnd = EntityUtil.CheckArgumentNull(toEnd, "toEnd"); AssociationSet = EntityUtil.CheckArgumentNull(associationSet, "associationSet"); StateEntry = EntityUtil.CheckArgumentNull(stateEntry, "stateEntry"); _equivalenceSetLinkedListNext = this; _hashCode = toEntityKey.GetHashCode() ^ fromEnd.GetHashCode() ^ toEnd.GetHashCode() ^ associationSet.GetHashCode(); }