示例#1
0
        private static bool CanBindTo(this IEdmFunctionImport function, IEdmCollectionType collection)
        {
            if (function == null)
            {
                throw Error.ArgumentNull("function");
            }
            if (collection == null)
            {
                throw Error.ArgumentNull("collection");
            }
            if (!function.IsBindable)
            {
                return(false);
            }

            // The binding parameter is the first parameter by convention
            IEdmFunctionParameter bindingParameter = function.Parameters.FirstOrDefault();

            if (bindingParameter == null)
            {
                return(false);
            }

            IEdmCollectionType bindingParameterType = bindingParameter.Type.Definition as IEdmCollectionType;

            if (bindingParameterType == null)
            {
                return(false);
            }

            IEdmEntityType bindingParameterElementType = bindingParameterType.ElementType.Definition as IEdmEntityType;
            IEdmEntityType entity = collection.ElementType.Definition as IEdmEntityType;

            if (bindingParameterElementType == null || entity == null)
            {
                return(false);
            }

            return(entity.IsOrInheritsFrom(bindingParameterElementType));
        }
        /// <summary>
        /// Verifies that CreateEntryReader or CreateFeedReader or CreateDeltaReader can be called.
        /// </summary>
        /// <param name="navigationSource">The navigation source we are going to read entities for.</param>
        /// <param name="entityType">The expected entity type for the entry/entries to be read.</param>
        private void VerifyCanCreateODataReader(IEdmNavigationSource navigationSource, IEdmEntityType entityType)
        {
            Debug.Assert(navigationSource == null || entityType != null, "If an navigation source is specified, the entity type must be specified as well.");

            // We require metadata information for reading requests.
            if (!this.ReadingResponse)
            {
                this.VerifyUserModel();

                if (navigationSource == null)
                {
                    throw new ODataException(ODataErrorStrings.ODataJsonLightInputContext_NoEntitySetForRequest);
                }
            }

            // We only check that the base type of the entity set is assignable from the specified entity type.
            // If no entity set/entity type is specified in the API, we will read it from the context URI.
            IEdmEntityType entitySetElementType = this.EdmTypeResolver.GetElementType(navigationSource);

            if (navigationSource != null && entityType != null && !entityType.IsOrInheritsFrom(entitySetElementType))
            {
                throw new ODataException(ODataErrorStrings.ODataJsonLightInputContext_EntityTypeMustBeCompatibleWithEntitySetBaseType(entityType.FullName(), entitySetElementType.FullName(), navigationSource.FullNavigationSourceName()));
            }
        }
示例#3
0
        /// <summary>
        /// Process the operation candidates using the information.
        /// </summary>
        /// <param name="context">The controller and action context.</param>
        /// <param name="entityType">The Edm entity type.</param>
        /// <param name="navigationSource">The Edm navigation source.</param>
        protected void ProcessOperations(ODataControllerActionContext context, IEdmEntityType entityType, IEdmNavigationSource navigationSource)
        {
            Contract.Assert(context != null);
            Contract.Assert(entityType != null);
            Contract.Assert(navigationSource != null);

            string actionName = context.Action.ActionMethod.Name;

            bool hasKeyParameter = context.Action.HasODataKeyParameter(entityType);

            if (context.Singleton != null && hasKeyParameter)
            {
                // Singleton doesn't allow to call action with key.
                return;
            }

            // OperationNameOnCollectionOfEntityType
            string operationName = SplitActionName(actionName, out string cast, out bool isOnCollection);

            IEdmEntityType castTypeFromActionName = null;

            if (cast != null)
            {
                castTypeFromActionName = entityType.FindTypeInInheritance(context.Model, cast) as IEdmEntityType;
                if (castTypeFromActionName == null)
                {
                    return;
                }
            }

            // TODO: refactor here
            // If we have mulitple same function defined, we should match the best one?
            IEnumerable <IEdmOperation> candidates = context.Model.SchemaElements.OfType <IEdmOperation>().Where(f => f.IsBound && f.Name == operationName);

            foreach (IEdmOperation edmOperation in candidates)
            {
                IEdmOperationParameter bindingParameter = edmOperation.Parameters.FirstOrDefault();
                if (bindingParameter == null)
                {
                    // bound operation at least has one parameter which type is the binding type.
                    continue;
                }

                IEdmTypeReference bindingType = bindingParameter.Type;
                bool bindToCollection         = bindingType.TypeKind() == EdmTypeKind.Collection;
                if (bindToCollection)
                {
                    // if binding to collection the action has key parameter or a singleton, skip
                    if (context.Singleton != null || hasKeyParameter)
                    {
                        continue;
                    }
                }
                else
                {
                    // if binding to non-collection and the action hasn't key parameter, skip
                    if (isOnCollection || (context.EntitySet != null && !hasKeyParameter))
                    {
                        continue;
                    }
                }

                // We only allow the binding type is entity type or collection of entity type.
                if (!bindingType.Definition.IsEntityOrEntityCollectionType(out IEdmEntityType bindingEntityType))
                {
                    continue;
                }

                IEdmEntityType castType = null;
                if (castTypeFromActionName == null)
                {
                    if (entityType.IsOrInheritsFrom(bindingEntityType))
                    {
                        // True if and only if the thisType is equivalent to or inherits from otherType.
                        castType = null;
                    }
                    else if (bindingEntityType.InheritsFrom(entityType))
                    {
                        // True if and only if the type inherits from the potential base type.
                        castType = bindingEntityType;
                    }
                    else
                    {
                        continue;
                    }
                }
                else
                {
                    if (isOnCollection && !bindToCollection)
                    {
                        continue;
                    }

                    if (bindingEntityType != castTypeFromActionName)
                    {
                        continue;
                    }

                    if (castTypeFromActionName != entityType)
                    {
                        castType = castTypeFromActionName;
                    }
                }

                // TODO: need discussion ahout:
                // 1) Do we need to match the whole parameter count?
                // 2) Do we need to select the best match? So far, i don't think and let it go.
                if (!IsOperationParameterMeet(edmOperation, context.Action))
                {
                    continue;
                }

                AddSelector(context, edmOperation, hasKeyParameter, entityType, navigationSource, castType);
            }
        }
示例#4
0
        public static bool CanBindTo(this IEdmFunctionImport function, IEdmEntityType entity)
        {
            if (function == null)
            {
                throw Error.ArgumentNull("function");
            }
            if (entity == null)
            {
                throw Error.ArgumentNull("entity");
            }
            if (!function.IsBindable)
            {
                return false;
            }

            // The binding parameter is the first parameter by convention
            IEdmFunctionParameter bindingParameter = function.Parameters.FirstOrDefault();
            if (bindingParameter == null)
            {
                return false;
            }

            IEdmEntityType bindingParameterType = bindingParameter.Type.Definition as IEdmEntityType;
            if (bindingParameterType == null)
            {
                return false;
            }

            return entity.IsOrInheritsFrom(bindingParameterType);
        }
        /// <summary>
        /// Parses the next OData path segment following an entity.
        /// </summary>
        /// <param name="model">The model to use for path parsing.</param>
        /// <param name="previous">The previous path segment.</param>
        /// <param name="previousEdmType">The EDM type of the OData path up to the previous segment.</param>
        /// <param name="segment">The value of the segment to parse.</param>
        /// <param name="segments">The queue of pending segments.</param>
        /// <returns>A parsed representation of the segment.</returns>
        protected virtual ODataPathSegment ParseAtEntity(IEdmModel model, ODataPathSegment previous,
                                                         IEdmType previousEdmType, string segment, Queue <string> segments)
        {
            if (previous == null)
            {
                throw Error.ArgumentNull("previous");
            }
            if (segments == null)
            {
                throw Error.ArgumentNull("segments");
            }
            if (String.IsNullOrEmpty(segment))
            {
                throw Error.Argument(SRResources.SegmentNullOrEmpty);
            }
            IEdmEntityType previousType = previousEdmType as IEdmEntityType;

            if (previousType == null)
            {
                throw Error.Argument(SRResources.PreviousSegmentMustBeEntityType, previousEdmType);
            }

            // first look for navigation properties
            IEdmNavigationProperty navigation = previousType.NavigationProperties().SingleOrDefault(np => np.Name == segment);

            if (navigation != null)
            {
                return(new NavigationPathSegment(navigation));
            }

            // next look for properties
            IEdmProperty property = previousType.Properties().SingleOrDefault(p => p.Name == segment);

            if (property != null)
            {
                return(new PropertyAccessPathSegment(property));
            }

            // next look for type casts
            IEdmEntityType castType = model.FindDeclaredType(segment) as IEdmEntityType;

            if (castType != null)
            {
                if (!castType.IsOrInheritsFrom(previousType) && !previousType.IsOrInheritsFrom(castType))
                {
                    throw new ODataException(Error.Format(SRResources.InvalidCastInPath, castType, previousType));
                }
                return(new CastPathSegment(castType));
            }

            // look for $ref
            if (segment == ODataSegmentKinds.Ref)
            {
                return(new RefPathSegment());
            }

            // finally look for bindable procedures
            IEdmAction action = model.FindAction(segment, previousType);

            if (action != null)
            {
                return(new BoundActionPathSegment(action));
            }

            // Try to match this to a function call
            BoundFunctionPathSegment pathSegment = TryMatchBoundFunctionCall(segment, segments, model, bindingType: previousType);

            if (pathSegment != null)
            {
                return(pathSegment);
            }

            // Treating as an open property
            return(new UnresolvedPathSegment(segment));
        }
        /// <summary>
        /// Parses the next OData path segment following an entity collection.
        /// </summary>
        /// <param name="model">The model to use for path parsing.</param>
        /// <param name="previous">The previous path segment.</param>
        /// <param name="previousEdmType">The EDM type of the OData path up to the previous segment.</param>
        /// <param name="segment">The value of the segment to parse.</param>
        /// <param name="segments">The queue of pending segments.</param>
        /// <returns>A parsed representation of the segment.</returns>
        protected virtual ODataPathSegment ParseAtEntityCollection(IEdmModel model, ODataPathSegment previous,
                                                                   IEdmType previousEdmType, string segment, Queue <string> segments)
        {
            if (previous == null)
            {
                throw Error.ArgumentNull("previous");
            }
            if (segments == null)
            {
                throw Error.ArgumentNull("segments");
            }
            if (String.IsNullOrEmpty(segment))
            {
                throw Error.Argument(SRResources.SegmentNullOrEmpty);
            }

            if (previousEdmType == null)
            {
                throw Error.InvalidOperation(SRResources.PreviousSegmentEdmTypeCannotBeNull);
            }
            IEdmCollectionType collectionType = previousEdmType as IEdmCollectionType;

            if (collectionType == null)
            {
                throw Error.Argument(SRResources.PreviousSegmentMustBeEntityCollectionType, previousEdmType);
            }
            IEdmEntityType elementType = collectionType.ElementType.Definition as IEdmEntityType;

            if (elementType == null)
            {
                throw Error.Argument(SRResources.PreviousSegmentMustBeEntityCollectionType, previousEdmType);
            }

            // look for keys first.
            if (segment.StartsWith("(", StringComparison.Ordinal) && segment.EndsWith(")", StringComparison.Ordinal))
            {
                Contract.Assert(segment.Length >= 2);
                string value = segment.Substring(1, segment.Length - 2);
                return(new KeyValuePathSegment(value));
            }

            // next look for casts
            IEdmEntityType castType = model.FindDeclaredType(segment) as IEdmEntityType;

            if (castType != null)
            {
                IEdmType previousElementType = collectionType.ElementType.Definition;
                if (!castType.IsOrInheritsFrom(previousElementType) && !previousElementType.IsOrInheritsFrom(castType))
                {
                    throw new ODataException(Error.Format(SRResources.InvalidCastInPath, castType, previousElementType));
                }
                return(new CastPathSegment(castType));
            }

            // look for $ref
            if (segment == ODataSegmentKinds.Ref)
            {
                return(new RefPathSegment());
            }

            // now look for bindable actions
            IEdmAction action = model.FindAction(segment, collectionType);

            if (action != null)
            {
                return(new BoundActionPathSegment(action));
            }

            // Try to match this to a function call
            BoundFunctionPathSegment pathSegment = TryMatchBoundFunctionCall(segment, segments, model, bindingType: collectionType);

            if (pathSegment != null)
            {
                return(pathSegment);
            }

            throw new ODataException(Error.Format(SRResources.NoActionFoundForCollection, segment, collectionType.ElementType));
        }
示例#7
0
        internal Expression CreatePropertyValueExpressionWithFilter(IEdmEntityType elementType, IEdmProperty property,
                                                                    Expression source, FilterClause filterClause)
        {
            Contract.Assert(elementType != null);
            Contract.Assert(property != null);
            Contract.Assert(source != null);

            IEdmEntityType declaringType = property.DeclaringType as IEdmEntityType;

            Contract.Assert(declaringType != null, "only entity types are projected.");

            // derived property using cast
            if (!elementType.IsOrInheritsFrom(declaringType))
            {
                Type castType = EdmLibHelpers.GetClrType(declaringType, _model);
                if (castType == null)
                {
                    throw new ODataException(Error.Format(SRResources.MappingDoesNotContainResourceType,
                                                          declaringType.FullName()));
                }

                source = Expression.TypeAs(source, castType);
            }

            string     propertyName          = EdmLibHelpers.GetClrPropertyName(property, _model);
            Expression propertyValue         = Expression.Property(source, propertyName);
            Type       nullablePropertyType  = TypeHelper.ToNullable(propertyValue.Type);
            Expression nullablePropertyValue = ExpressionHelpers.ToNullable(propertyValue);

            if (filterClause != null)
            {
                bool isCollection = property.Type.IsCollection();

                IEdmTypeReference edmElementType = (isCollection ? property.Type.AsCollection().ElementType() : property.Type);
                Type clrElementType = EdmLibHelpers.GetClrType(edmElementType, _model);
                if (clrElementType == null)
                {
                    throw new ODataException(Error.Format(SRResources.MappingDoesNotContainResourceType,
                                                          edmElementType.FullName()));
                }

                Expression filterResult = nullablePropertyValue;

                ODataQuerySettings querySettings = new ODataQuerySettings()
                {
                    HandleNullPropagation = HandleNullPropagationOption.True,
                };

                if (isCollection)
                {
                    Expression filterSource =
                        typeof(IEnumerable).IsAssignableFrom(source.Type.GetProperty(propertyName).PropertyType)
                            ? Expression.Call(
                            ExpressionHelperMethods.QueryableAsQueryable.MakeGenericMethod(clrElementType),
                            nullablePropertyValue)
                            : nullablePropertyValue;

                    // TODO: Implement proper support for $select/$expand after $apply
                    Expression filterPredicate = FilterBinder.Bind(null, filterClause, clrElementType, _context, querySettings);
                    filterResult = Expression.Call(
                        ExpressionHelperMethods.QueryableWhereGeneric.MakeGenericMethod(clrElementType),
                        filterSource,
                        filterPredicate);

                    nullablePropertyType = filterResult.Type;
                }
                else if (_settings.HandleReferenceNavigationPropertyExpandFilter)
                {
                    LambdaExpression filterLambdaExpression = FilterBinder.Bind(null, filterClause, clrElementType, _context, querySettings) as LambdaExpression;
                    if (filterLambdaExpression == null)
                    {
                        throw new ODataException(Error.Format(SRResources.ExpandFilterExpressionNotLambdaExpression,
                                                              property.Name, "LambdaExpression"));
                    }

                    ParameterExpression filterParameter     = filterLambdaExpression.Parameters.First();
                    Expression          predicateExpression = new ReferenceNavigationPropertyExpandFilterVisitor(filterParameter, nullablePropertyValue).Visit(filterLambdaExpression.Body);

                    // create expression similar to: 'predicateExpression == true ? nullablePropertyValue : null'
                    filterResult = Expression.Condition(
                        test: predicateExpression,
                        ifTrue: nullablePropertyValue,
                        ifFalse: Expression.Constant(value: null, type: nullablePropertyType));
                }

                if (_settings.HandleNullPropagation == HandleNullPropagationOption.True)
                {
                    // create expression similar to: 'nullablePropertyValue == null ? null : filterResult'
                    nullablePropertyValue = Expression.Condition(
                        test: Expression.Equal(nullablePropertyValue, Expression.Constant(value: null)),
                        ifTrue: Expression.Constant(value: null, type: nullablePropertyType),
                        ifFalse: filterResult);
                }
                else
                {
                    nullablePropertyValue = filterResult;
                }
            }

            if (_settings.HandleNullPropagation == HandleNullPropagationOption.True)
            {
                // create expression similar to: 'source == null ? null : propertyValue'
                propertyValue = Expression.Condition(
                    test: Expression.Equal(source, Expression.Constant(value: null)),
                    ifTrue: Expression.Constant(value: null, type: nullablePropertyType),
                    ifFalse: nullablePropertyValue);
            }
            else
            {
                // need to cast this to nullable as EF would fail while materializing if the property is not nullable and source is null.
                propertyValue = nullablePropertyValue;
            }

            return(propertyValue);
        }
        /// <summary>
        /// Verifies that CreateEntryReader or CreateFeedReader or CreateDeltaReader can be called.
        /// </summary>
        /// <param name="navigationSource">The navigation source we are going to read entities for.</param>
        /// <param name="entityType">The expected entity type for the entry/entries to be read.</param>
        private void VerifyCanCreateODataReader(IEdmNavigationSource navigationSource, IEdmEntityType entityType)
        {
            Debug.Assert(navigationSource == null || entityType != null, "If an navigation source is specified, the entity type must be specified as well.");

            // We require metadata information for reading requests.
            if (!this.ReadingResponse)
            {
                this.VerifyUserModel();

                if (navigationSource == null)
                {
                    throw new ODataException(ODataErrorStrings.ODataJsonLightInputContext_NoEntitySetForRequest);
                }
            }

            // We only check that the base type of the entity set is assignable from the specified entity type.
            // If no entity set/entity type is specified in the API, we will read it from the context URI.
            IEdmEntityType entitySetElementType = this.EdmTypeResolver.GetElementType(navigationSource);
            if (navigationSource != null && entityType != null && !entityType.IsOrInheritsFrom(entitySetElementType))
            {
                throw new ODataException(ODataErrorStrings.ODataJsonLightInputContext_EntityTypeMustBeCompatibleWithEntitySetBaseType(entityType.FullName(), entitySetElementType.FullName(), navigationSource.FullNavigationSourceName()));
            }
        }
        /// <summary>
        /// Process the operation candidates using the information.
        /// </summary>
        /// <param name="context">The controller and action context.</param>
        /// <param name="entityType">The Edm entity type.</param>
        /// <param name="navigationSource">The Edm navigation source.</param>
        protected void ProcessOperations(ODataControllerActionContext context, IEdmEntityType entityType, IEdmNavigationSource navigationSource)
        {
            Contract.Assert(context != null);
            Contract.Assert(entityType != null);
            Contract.Assert(navigationSource != null);

            string actionName = context.Action.ActionName;

            bool hasKeyParameter = context.Action.HasODataKeyParameter(entityType, context.Options?.RouteOptions?.EnablePropertyNameCaseInsensitive ?? false);

            if (context.Singleton != null && hasKeyParameter)
            {
                // Singleton doesn't allow to call action with key.
                return;
            }

            bool           isOnCollection         = false;
            IEdmEntityType castTypeFromActionName = null;

            IEdmOperation[] candidates = FindCandidates(context, actionName);
            if (candidates.Length == 0)
            {
                // If we can't find any Edm operation using the action name directly,
                // Let's split the action name and use part of it to search again.
                candidates = FindCandidates(context, entityType, actionName, out castTypeFromActionName, out isOnCollection);
            }

            foreach (IEdmOperation edmOperation in candidates)
            {
                IEdmOperationParameter bindingParameter = edmOperation.Parameters.FirstOrDefault();
                if (bindingParameter == null)
                {
                    // bound operation at least has one parameter which type is the binding type.
                    continue;
                }

                IEdmTypeReference bindingType = bindingParameter.Type;
                bool bindToCollection         = bindingType.TypeKind() == EdmTypeKind.Collection;
                if (bindToCollection)
                {
                    // if binding to collection the action has key parameter or a singleton, skip
                    if (context.Singleton != null || hasKeyParameter)
                    {
                        continue;
                    }
                }
                else
                {
                    // if binding to non-collection and the action hasn't key parameter, skip
                    if (isOnCollection || (context.EntitySet != null && !hasKeyParameter))
                    {
                        continue;
                    }
                }

                // We only allow the binding type is entity type or collection of entity type.
                if (!bindingType.Definition.IsEntityOrEntityCollectionType(out IEdmEntityType bindingEntityType))
                {
                    continue;
                }

                IEdmEntityType castType = null;
                if (castTypeFromActionName == null)
                {
                    if (entityType.IsOrInheritsFrom(bindingEntityType))
                    {
                        // True if and only if the thisType is equivalent to or inherits from otherType.
                        castType = null;
                    }
                    else if (bindingEntityType.InheritsFrom(entityType))
                    {
                        // True if and only if the type inherits from the potential base type.
                        castType = bindingEntityType;
                    }
                    else
                    {
                        continue;
                    }
                }
                else
                {
                    if (isOnCollection && !bindToCollection)
                    {
                        continue;
                    }

                    if (bindingEntityType != castTypeFromActionName)
                    {
                        continue;
                    }

                    if (castTypeFromActionName != entityType)
                    {
                        castType = castTypeFromActionName;
                    }
                }

                // TODO: need discussion about:
                // 1) Do we need to match the whole parameter count?
                // 2) Do we need to select the best match? So far, i don't think and let it go.
                if (!IsOperationParameterMatched(edmOperation, context.Action))
                {
                    continue;
                }

                AddSelector(context, edmOperation, hasKeyParameter, entityType, navigationSource, castType);
            }
        }
示例#10
0
        /// <summary>
        /// Parses the next OData path segment following an entity.
        /// </summary>
        /// <param name="model">The model to use for path parsing.</param>
        /// <param name="previous">The previous path segment.</param>
        /// <param name="previousEdmType">The EDM type of the OData path up to the previous segment.</param>
        /// <param name="segment">The value of the segment to parse.</param>
        /// <returns>A parsed representation of the segment.</returns>
        protected virtual ODataPathSegment ParseAtEntity(IEdmModel model, ODataPathSegment previous, IEdmType previousEdmType, string segment)
        {
            if (previous == null)
            {
                throw Error.ArgumentNull("previous");
            }
            if (String.IsNullOrEmpty(segment))
            {
                throw Error.Argument(SRResources.SegmentNullOrEmpty);
            }
            IEdmEntityType previousType = previousEdmType as IEdmEntityType;

            if (previousType == null)
            {
                throw Error.Argument(SRResources.PreviousSegmentMustBeEntityType, previousEdmType);
            }

            if (segment == ODataSegmentKinds.Links)
            {
                return(new LinksPathSegment());
            }

            // first look for navigation properties
            IEdmNavigationProperty navigation = previousType.NavigationProperties().SingleOrDefault(np => np.Name == segment);

            if (navigation != null)
            {
                return(new NavigationPathSegment(navigation));
            }

            // next look for properties
            IEdmProperty property = previousType.Properties().SingleOrDefault(p => p.Name == segment);

            if (property != null)
            {
                return(new PropertyAccessPathSegment(property));
            }

            // next look for type casts
            IEdmEntityType castType = model.FindDeclaredType(segment) as IEdmEntityType;

            if (castType != null)
            {
                if (!castType.IsOrInheritsFrom(previousType))
                {
                    throw new ODataException(Error.Format(SRResources.InvalidCastInPath, castType, previousType));
                }
                return(new CastPathSegment(castType));
            }

            // finally look for bindable procedures
            IEdmEntityContainer container = ExtractEntityContainer(model);
            IEdmFunctionImport  procedure = container.FunctionImports().FindBindableAction(previousType, segment);

            if (procedure != null)
            {
                return(new ActionPathSegment(procedure));
            }

            // Treating as an open property
            return(new UnresolvedPathSegment(segment));
        }
示例#11
0
		internal static bool TypeIndirectlyContainsTarget(IEdmEntityType source, IEdmEntityType target, HashSetInternal<IEdmEntityType> visited, IEdmModel context)
		{
			bool flag;
			if (visited.Add(source))
			{
				if (!source.IsOrInheritsFrom(target))
				{
					foreach (IEdmNavigationProperty edmNavigationProperty in source.NavigationProperties())
					{
						if (!edmNavigationProperty.ContainsTarget || !ValidationHelper.TypeIndirectlyContainsTarget(edmNavigationProperty.ToEntityType(), target, visited, context))
						{
							continue;
						}
						flag = true;
						return flag;
					}
					IEnumerator<IEdmStructuredType> enumerator = context.FindAllDerivedTypes(source).GetEnumerator();
					using (enumerator)
					{
						while (enumerator.MoveNext())
						{
							IEdmStructuredType current = enumerator.Current;
							IEdmEntityType edmEntityType = current as IEdmEntityType;
							if (edmEntityType == null || !ValidationHelper.TypeIndirectlyContainsTarget(edmEntityType, target, visited, context))
							{
								continue;
							}
							flag = true;
							return flag;
						}
						return false;
					}
					return flag;
				}
				else
				{
					return true;
				}
			}
			return false;
		}
示例#12
0
        internal static bool TypeIndirectlyContainsTarget(IEdmEntityType source, IEdmEntityType target, HashSetInternal<IEdmEntityType> visited, IEdmModel context)
        {
            if (visited.Add(source))
            {
                if (source.IsOrInheritsFrom(target))
                {
                    return true;
                }

                foreach (IEdmNavigationProperty navProp in source.NavigationProperties())
                {
                    if (navProp.ContainsTarget && TypeIndirectlyContainsTarget(navProp.ToEntityType(), target, visited, context))
                    {
                        return true;
                    }
                }

                foreach (IEdmStructuredType derived in context.FindAllDerivedTypes(source))
                {
                    IEdmEntityType derivedEntity = derived as IEdmEntityType;
                    if (derivedEntity != null && TypeIndirectlyContainsTarget(derivedEntity, target, visited, context))
                    {
                        return true;
                    }
                }
            }

            return false;
        }