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