/// <summary>
        /// Adds an entity set backed by the <paramref name="resourceSet"/> to the entity container.
        /// </summary>
        /// <param name="entitySetName">The name of the entity set.</param>
        /// <param name="resourceSet">The resource set backing the entity set to be created.</param>
        /// <returns>an instance of IEdmEntitySet that just got added.</returns>
        /// <remarks>
        /// This method will also create the association sets and associations for the entity set.
        /// Materialization state: EntityContainers required. No change in materialization state.
        /// </remarks>
        internal IEdmEntitySet AddEntitySet(string entitySetName, ResourceSetWrapper resourceSet)
        {
            Debug.Assert(!string.IsNullOrEmpty(entitySetName), "!string.IsNullOrEmpty(entitySetName)");
            Debug.Assert(resourceSet != null, "resourceSet != null");

            IEdmEntitySet entitySet = new MetadataProviderEdmEntitySet(this.model, this, resourceSet);

            MetadataProviderUtils.ConvertCustomAnnotations(this.model, resourceSet.CustomAnnotations, entitySet);
            this.entitySetCache.Add(entitySetName, entitySet);
            return(entitySet);
        }
        /// <summary>
        /// Finds the entity set that this navigation property refers to.
        /// </summary>
        /// <param name="navigationProperty">Instance of navigation property.</param>
        /// <returns>an instance of IEdmEntitySet that this navigation property refers to.</returns>
        public IEdmNavigationSource FindNavigationTarget(IEdmNavigationProperty navigationProperty)
        {
            WebUtil.CheckArgumentNull(navigationProperty, "navigationProperty");
            MetadataProviderEdmEntitySet targetEntitySet = null;

            if (this.navigationTargetMapping == null || !this.navigationTargetMapping.TryGetValue(navigationProperty, out targetEntitySet))
            {
                string           declaringTypeName          = navigationProperty.DeclaringEntityType().FullName();
                ResourceType     declaringResourceType      = this.model.MetadataProvider.TryResolveResourceType(declaringTypeName);
                ResourceProperty navigationResourceProperty = declaringResourceType.TryResolvePropertiesDeclaredOnThisTypeByName(navigationProperty.Name);

                if (navigationResourceProperty != null && navigationResourceProperty.TypeKind == ResourceTypeKind.EntityType)
                {
                    // Calling this method causes the model to load all the metadata for the given association.
                    // Hence we do not need to add this to the target mapping explicitly
                    this.model.PairUpNavigationProperty(this.resourceSet, declaringResourceType, navigationResourceProperty);

                    // Since the entity set or target entity set might be hidden, the navigation target might not get added
                    // from the previous call
                    if (this.navigationTargetMapping != null)
                    {
                        this.navigationTargetMapping.TryGetValue(navigationProperty, out targetEntitySet);
                    }
                }
            }

            if (this.model.Mode == MetadataProviderEdmModelMode.SelectAndExpandParsing)
            {
                // When parsing $select/$expand, the URI parser has no way of knowing which sets are visible. So, if a navigation property is found
                // that does not have a target entity set, then it means that the target set is hidden. To avoid disclosing the existence of the set, act
                // as if the property does not exist.
                if (targetEntitySet == null)
                {
                    // We're playing a dangerous game here. We are trying to throw the SAME ERROR MESSAGE that the Uri Parser would throw
                    // for some property that is not found. If it looks any different, a client could detect the difference and learn about
                    // the existance of a navigation property that should have been hidden.
                    throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidPropertyNameSpecified(navigationProperty.Name, navigationProperty.DeclaringEntityType().FullName()));
                }
            }

            if (this.model.Mode == MetadataProviderEdmModelMode.UriPathParsing)
            {
                // As with select and expand, when parsing the path, the URI parser has no way of knowing which sets are visible. See above.
                if (targetEntitySet == null)
                {
                    // Same fragility as above.
                    throw DataServiceException.CreateResourceNotFound(navigationProperty.Name);
                }
            }

            return(targetEntitySet);
        }
        /// <summary>
        /// Adds an entity set backed by the <paramref name="resourceSet"/> to the entity container.
        /// </summary>
        /// <param name="entitySetName">The name of the entity set.</param>
        /// <param name="resourceSet">The resource set backing the entity set to be created.</param>
        /// <returns>an instance of IEdmEntitySet that just got added.</returns>
        /// <remarks>
        /// This method will also create the association sets and associations for the entity set.
        /// Materialization state: EntityContainers required. No change in materialization state.
        /// </remarks>
        internal IEdmEntitySet AddEntitySet(string entitySetName, ResourceSetWrapper resourceSet)
        {
            Debug.Assert(!string.IsNullOrEmpty(entitySetName), "!string.IsNullOrEmpty(entitySetName)");
            Debug.Assert(resourceSet != null, "resourceSet != null");

            IEdmEntitySet entitySet = new MetadataProviderEdmEntitySet(this.model, this, resourceSet);
            MetadataProviderUtils.ConvertCustomAnnotations(this.model, resourceSet.CustomAnnotations, entitySet);
            this.entitySetCache.Add(entitySetName, entitySet);
            return entitySet;
        }
        /// <summary>
        /// Cache the entity set that the given navigation property refers to.
        /// </summary>
        /// <param name="navigationProperty">IEdmNavigationProperty that contains the navigation property metadata.</param>
        /// <param name="entitySet">Entityset that <paramref name="navigationProperty"/> refers to.</param>
        internal void EnsureNavigationTarget(IEdmNavigationProperty navigationProperty, MetadataProviderEdmEntitySet entitySet)
        {
            Debug.Assert(navigationProperty != null, "navigationProperty != null");
            Debug.Assert(entitySet != null, "entitySet != null");

            MetadataProviderEdmEntitySet targetEntitySet;

            if (this.navigationTargetMapping == null)
            {
                this.navigationTargetMapping = new Dictionary <IEdmNavigationProperty, MetadataProviderEdmEntitySet>(EqualityComparer <IEdmNavigationProperty> .Default);
            }

            if (!this.navigationTargetMapping.TryGetValue(navigationProperty, out targetEntitySet))
            {
                // Looks like this will get called multiple types for the same navigation property in MEST scenarios.
                // Looking at the EdmEntitySet, the last one wins. So keeping the same behavior here.
                this.navigationTargetMapping.Add(navigationProperty, entitySet);
            }
            else
            {
                Debug.Assert(targetEntitySet == entitySet, "targetEntitySet == entitySet");
            }
        }
예제 #5
0
        /// <summary>
        /// Cache the entity set that the given navigation property refers to.
        /// </summary>
        /// <param name="navigationProperty">IEdmNavigationProperty that contains the navigation property metadata.</param>
        /// <param name="entitySet">Entityset that <paramref name="navigationProperty"/> refers to.</param>
        internal void EnsureNavigationTarget(IEdmNavigationProperty navigationProperty, MetadataProviderEdmEntitySet entitySet)
        {
            Debug.Assert(navigationProperty != null, "navigationProperty != null");
            Debug.Assert(entitySet != null, "entitySet != null");

            string path = navigationProperty.Name;

            if (!this.Type.AsElementType().IsOrInheritsFrom(navigationProperty.DeclaringType))
            {
                path = navigationProperty.DeclaringType.FullTypeName() + '/' + path;
            }

            if (!this.navigationBindingMappings.ContainsKey(navigationProperty))
            {
                this.navigationBindingMappings[navigationProperty] = new Dictionary <string, IEdmNavigationPropertyBinding>();
            }

            this.navigationBindingMappings[navigationProperty][path] = new EdmNavigationPropertyBinding(navigationProperty, entitySet, new EdmPathExpression(path));
        }
        /// <summary>
        /// Cache the entity set that the given navigation property refers to.
        /// </summary>
        /// <param name="navigationProperty">IEdmNavigationProperty that contains the navigation property metadata.</param>
        /// <param name="entitySet">Entityset that <paramref name="navigationProperty"/> refers to.</param>
        internal void EnsureNavigationTarget(IEdmNavigationProperty navigationProperty, MetadataProviderEdmEntitySet entitySet)
        {
            Debug.Assert(navigationProperty != null, "navigationProperty != null");
            Debug.Assert(entitySet != null, "entitySet != null");

            MetadataProviderEdmEntitySet targetEntitySet;
            if (this.navigationTargetMapping == null)
            {
                this.navigationTargetMapping = new Dictionary<IEdmNavigationProperty, MetadataProviderEdmEntitySet>(EqualityComparer<IEdmNavigationProperty>.Default);
            }

            if (!this.navigationTargetMapping.TryGetValue(navigationProperty, out targetEntitySet))
            {
                // Looks like this will get called multiple types for the same navigation property in MEST scenarios.
                // Looking at the EdmEntitySet, the last one wins. So keeping the same behavior here.
                this.navigationTargetMapping.Add(navigationProperty, entitySet);
            }
            else
            {
                Debug.Assert(targetEntitySet == entitySet, "targetEntitySet == entitySet");
            }
        }