public override ResourceAssociationSet GetResourceAssociationSet(ResourceSet resourceSet, ResourceType resourceType, ResourceProperty resourceProperty) { WebUtil.CheckArgumentNull(resourceSet, "resourceSet"); WebUtil.CheckArgumentNull(resourceType, "resourceType"); WebUtil.CheckArgumentNull(resourceProperty, "resourceProperty"); // Get source set EntitySet sourceEntitySet = this.GetEntitySet(resourceSet.Name); Debug.Assert(sourceEntitySet != null, "entitySet != null -- GetEntitySet should never return null"); // Get the source type EntityType sourceEntityType = this.ObjectContext.MetadataWorkspace.GetItem<EntityType>(resourceType.FullName, DataSpace.CSpace); Debug.Assert(sourceEntityType != null, "entityType != null"); // Get source navigation property NavigationProperty sourceNavigationProperty; sourceEntityType.NavigationProperties.TryGetValue(resourceProperty.Name, false /*ignoreCase*/, out sourceNavigationProperty); if (sourceNavigationProperty == null) { throw new InvalidOperationException(Strings.BadProvider_PropertyMustBeNavigationPropertyOnType(resourceProperty.Name, resourceType.FullName)); } if (sourceEntityType != (EntityType)sourceNavigationProperty.DeclaringType || resourceType != resourceType.GetDeclaringTypeForProperty(resourceProperty)) { throw new InvalidOperationException(Strings.BadProvider_ResourceTypeMustBeDeclaringTypeForProperty(resourceType.FullName, resourceProperty.Name)); } ResourceAssociationSet result = null; foreach (AssociationSet associationSet in sourceEntitySet.EntityContainer.BaseEntitySets.OfType<AssociationSet>()) { if (associationSet.ElementType == sourceNavigationProperty.RelationshipType) { // from AssociationSetEnd AssociationSetEnd setEnd = associationSet.AssociationSetEnds[sourceNavigationProperty.FromEndMember.Name]; if (setEnd.EntitySet == sourceEntitySet) { // from ResourceAssociationSetEnd ResourceAssociationSetEnd thisAssociationSetEnd = ObjectContextServiceProvider.PopulateResourceAssociationSetEnd(setEnd, resourceSet, resourceType, resourceProperty); #if !EF6Provider // from ResourceAssociationTypeEnd ResourceAssociationTypeEnd thisAssociationTypeEnd = ObjectContextServiceProvider.PopulateResourceAssociationTypeEnd( setEnd.CorrespondingAssociationEndMember, resourceType, resourceProperty); #endif // to AssociationSetEnd setEnd = associationSet.AssociationSetEnds[sourceNavigationProperty.ToEndMember.Name]; // Get the target resource set EntitySet targetEntitySet = setEnd.EntitySet; string targetEntitySetName = GetEntitySetName(targetEntitySet.Name, targetEntitySet.EntityContainer.Name, this.ObjectContext.DefaultContainerName == targetEntitySet.EntityContainer.Name); ResourceSet targetResourceSet; ((IDataServiceMetadataProvider)this).TryResolveResourceSet(targetEntitySetName, out targetResourceSet); Debug.Assert(targetResourceSet != null, "targetResourceSet != null"); // Get the target resource type EntityType targetEntityType = (EntityType)((RefType)sourceNavigationProperty.ToEndMember.TypeUsage.EdmType).ElementType; ResourceType targetResourceType; ((IDataServiceMetadataProvider)this).TryResolveResourceType(targetEntityType.FullName, out targetResourceType); Debug.Assert(targetResourceType != null, "targetResourceType != null"); // Get the target resource property ResourceProperty targetResourceProperty = null; foreach (NavigationProperty navProperty in targetEntityType.NavigationProperties) { if (navProperty.ToEndMember == sourceNavigationProperty.FromEndMember) { targetResourceProperty = targetResourceType.TryResolvePropertyName(navProperty.Name, exceptKind: ResourcePropertyKind.Stream); break; } } // to ResourceAssociationSetEnd ResourceAssociationSetEnd relatedAssociationSetEnd = ObjectContextServiceProvider.PopulateResourceAssociationSetEnd( setEnd, targetResourceSet, targetResourceType, (resourceType == targetResourceType && resourceProperty == targetResourceProperty) ? null : targetResourceProperty); #if !EF6Provider // to ResourceAssociationTypeEnd ResourceAssociationTypeEnd relatedAssociationTypeEnd = ObjectContextServiceProvider.PopulateResourceAssociationTypeEnd( setEnd.CorrespondingAssociationEndMember, targetResourceType, relatedAssociationSetEnd.ResourceProperty); #endif result = new ResourceAssociationSet(associationSet.Name, thisAssociationSetEnd, relatedAssociationSetEnd); #if !EF6Provider ObjectContextServiceProvider.PopulateAnnotations(associationSet.MetadataProperties, result.AddCustomAnnotation); result.ResourceAssociationType = ObjectContextServiceProvider.PopulateResourceAssociationType( associationSet.ElementType, thisAssociationTypeEnd, relatedAssociationTypeEnd); #endif break; } } } return result; }
/// <summary> /// Gets the ResourceAssociationSet instance when given the source association end. /// </summary> /// <param name="resourceSet">Resource set of the source association end.</param> /// <param name="resourceType">Resource type of the source association end.</param> /// <param name="resourceProperty">Resource property of the source association end.</param> /// <returns>ResourceAssociationSet instance.</returns> public override ResourceAssociationSet GetResourceAssociationSet(ResourceSet resourceSet, ResourceType resourceType, ResourceProperty resourceProperty) { WebUtil.CheckArgumentNull(resourceSet, "resourceSet"); WebUtil.CheckArgumentNull(resourceType, "resourceType"); WebUtil.CheckArgumentNull(resourceProperty, "resourceProperty"); ResourceSet knownSet; if (!this.TryResolveResourceSet(resourceSet.Name, out knownSet) || knownSet != resourceSet) { throw new InvalidOperationException(Strings.BadProvider_UnknownResourceSet(resourceSet.Name)); } ResourceType knownType; if (!this.TryResolveResourceType(resourceType.FullName, out knownType) || knownType != resourceType) { throw new InvalidOperationException(Strings.BadProvider_UnknownResourceType(resourceType.FullName)); } if (resourceType != resourceType.GetDeclaringTypeForProperty(resourceProperty)) { throw new InvalidOperationException(Strings.BadProvider_ResourceTypeMustBeDeclaringTypeForProperty(resourceType.FullName, resourceProperty.Name)); } ResourceType targetType = resourceProperty.ResourceType; Debug.Assert(targetType != null, "targetType != null"); if (targetType.ResourceTypeKind != ResourceTypeKind.EntityType) { throw new InvalidOperationException(Strings.BadProvider_PropertyMustBeNavigationPropertyOnType(resourceProperty.Name, resourceType.FullName)); } ResourceSet targetSet = InternalGetContainerForResourceType(targetType.InstanceType, this.ResourceSets); Debug.Assert(targetSet != null, "targetSet != null"); // In order to prevent this from becoming a breaking change, we use the name to build up the association whenever possible. // If there exists an entity with the same name, then we try and use the full name. string associationSetName; if (this.MetadataCacheItem.ResourceTypeCacheItems.Count(rt => rt.ResourceType.Name == resourceType.Name) > 1) { associationSetName = resourceType.FullName.Replace('.', '_') + '_' + resourceProperty.Name; } else { associationSetName = resourceType.Name + '_' + resourceProperty.Name; } // We changed the association logic on the server to create the correct navigation property for V4 to run the tests. // The association logic on server side needs to be removed. // Calculating targetResourceProperty value here is for V4 and it is not the correct code for V3. ResourceProperty targetResourceProperty = null; if (targetType != resourceType) { targetResourceProperty = GetResourcePropertyByResourcePropertyTypeInResourceSet(resourceType, targetSet); } else { targetResourceProperty = resourceProperty; } if (targetResourceProperty != null && !this.MetadataCacheItem.TargetResourcePropertiesCacheItems.ContainsKey(targetSet.Name + "_" + targetResourceProperty.Name)) { this.MetadataCacheItem.TargetResourcePropertiesCacheItems.Add(targetSet.Name + "_" + targetResourceProperty.Name, resourceProperty); } ResourceAssociationSetEnd sourceEnd = new ResourceAssociationSetEnd(resourceSet, resourceType, resourceProperty); ResourceAssociationSetEnd targetEnd = new ResourceAssociationSetEnd(targetSet, targetType, targetResourceProperty); return new ResourceAssociationSet(associationSetName, sourceEnd, targetEnd); }