public void OrderByOptionSetCorrectly()
 {
     SingleValuePropertyAccessNode propertyAccessNode = new SingleValuePropertyAccessNode(new ConstantNode(1), HardCodedTestModel.GetPersonNameProp());
     OrderByClause orderBy = new OrderByClause(null, propertyAccessNode, OrderByDirection.Descending, new EntityRangeVariable(ExpressionConstants.It, HardCodedTestModel.GetPersonTypeReference(), HardCodedTestModel.GetPeopleSet()));
     ExpandedNavigationSelectItem expansion = new ExpandedNavigationSelectItem(new ODataExpandPath(new NavigationPropertySegment(ModelBuildingHelpers.BuildValidNavigationProperty(), null)), HardCodedTestModel.GetPeopleSet(), null, null, orderBy, null, null, null, null, null);
     expansion.OrderByOption.Expression.ShouldBeSingleValuePropertyAccessQueryNode(HardCodedTestModel.GetPersonNameProp());
 }
        private void ValidateExpandedItem(ExpandedNavigationSelectItem item)
        {
            // If the navigation source doesn't exist, means that we are in query composition mode, so we just examine
            // the $expand path (The list of navigation properties) and check the annotations on their IEdmTypes.
            if (item.NavigationSource != null && CanAccess(item.NavigationSource.EntityType()))
            {
                foreach (var element in GetExpandedProperties(item.SelectAndExpand))
                {
                    ValidateExpandedItem(element);
                }
            }
            else if (item.NavigationSource == null)
            {
                IEnumerable<NavigationPropertySegment> path = item.PathToNavigationProperty.OfType<NavigationPropertySegment>();
                ValidateExpandedPath(path);
            }
            else
            {
                var segment = item.PathToNavigationProperty.OfType<NavigationPropertySegment>().First();
                string message = string.Format("Not authorized to expand the navigation property '{0}'",
                    segment.NavigationProperty.Name);

                throw new ODataException(message);
            }
        }
 public void FilterOptionSetCorrectly()
 {
     BinaryOperatorNode filterExpression = new BinaryOperatorNode(BinaryOperatorKind.Equal, new ConstantNode(1), new ConstantNode(1));
     FilterClause filterClause = new FilterClause(filterExpression, new EntityRangeVariable(ExpressionConstants.It, HardCodedTestModel.GetPersonTypeReference(), HardCodedTestModel.GetPeopleSet()));
     ExpandedNavigationSelectItem expansion = new ExpandedNavigationSelectItem(new ODataExpandPath(new NavigationPropertySegment(ModelBuildingHelpers.BuildValidNavigationProperty(), null)), HardCodedTestModel.GetPeopleSet(), null, filterClause, null, null, null, null, null, null);
     expansion.FilterOption.Expression.ShouldBeBinaryOperatorNode(BinaryOperatorKind.Equal);
     expansion.FilterOption.Expression.As<BinaryOperatorNode>().Left.ShouldBeConstantQueryNode(1);
     expansion.FilterOption.Expression.As<BinaryOperatorNode>().Right.ShouldBeConstantQueryNode(1);
 }
        public void TryEnableNoDollarSignSystemQueryOption(string relativeUri)
        {
            // Create parser specifying optional-$-sign setting.
            var parser = new ODataUriParser(GetModel(), new Uri(relativeUri, UriKind.Relative))
            {
                EnableNoDollarQueryOptions = true
            };

            // Verify path is parsed correctly.
            Microsoft.OData.UriParser.ODataPath path = parser.ParsePath();
            Assert.NotNull(path);
            Assert.Equal(path.Count, 2);

            // Verify expand & select clause is parsed correctly.
            SelectExpandClause result = parser.ParseSelectAndExpand();

            Assert.NotNull(result);
            Assert.Equal(result.SelectedItems.Count(), 1);
            ExpandedNavigationSelectItem selectItems = (result.SelectedItems.First() as ExpandedNavigationSelectItem);

            Assert.NotNull(selectItems);
            Assert.Equal(selectItems.NavigationSource.Name, "PermanentAccount");
            Assert.Equal(selectItems.SelectAndExpand.SelectedItems.Count(), 2);
        }
        public void ProjectAsWrapper_NullExpandedProperty_HasNullValueInProjectedWrapper()
        {
            // Arrange
            IPropertyMapper mapper = new IdentityPropertyMapper();
            Order           order  = new Order();
            ExpandedNavigationSelectItem expandItem = new ExpandedNavigationSelectItem(
                new ODataExpandPath(new NavigationPropertySegment(_model.Order.NavigationProperties().Single(), navigationSource: _model.Customers)),
                _model.Customers,
                selectExpandOption: null);
            SelectExpandClause selectExpand = new SelectExpandClause(new SelectItem[] { expandItem }, allSelected: true);
            Expression         source       = Expression.Constant(order);

            _model.Model.SetAnnotationValue(_model.Order, new DynamicPropertyDictionaryAnnotation(typeof(Order).GetProperty("OrderProperties")));

            // Act
            Expression projection = _binder.ProjectAsWrapper(source, selectExpand, _model.Order, _model.Orders);

            // Assert
            SelectExpandWrapper <Order> projectedOrder = Expression.Lambda(projection).Compile().DynamicInvoke() as SelectExpandWrapper <Order>;

            Assert.NotNull(projectedOrder);
            Assert.Contains("Customer", projectedOrder.Container.ToDictionary(mapper).Keys);
            Assert.Null(projectedOrder.Container.ToDictionary(mapper)["Customer"]);
        }
示例#6
0
        private ExpandedNavigationSelectItem Build(ExpandedNavigationSelectItem navigationSelectItem)
        {
            if (navigationSelectItem.SelectAndExpand == null)
                return navigationSelectItem;

            var segment = (NavigationPropertySegment)navigationSelectItem.PathToNavigationProperty.LastSegment;
            IEdmNavigationProperty navigationProperty = segment.NavigationProperty;

            SelectExpandClause selectExpandClause = GetSelectItems(navigationSelectItem.SelectAndExpand, _modelBoundProvider.GetSettings(navigationProperty));
            if (selectExpandClause == navigationSelectItem.SelectAndExpand)
                return navigationSelectItem;

            return new ExpandedNavigationSelectItem(
                navigationSelectItem.PathToNavigationProperty,
                navigationSelectItem.NavigationSource,
                selectExpandClause,
                navigationSelectItem.FilterOption,
                navigationSelectItem.OrderByOption,
                navigationSelectItem.TopOption,
                navigationSelectItem.SkipOption,
                navigationSelectItem.CountOption,
                navigationSelectItem.SearchOption,
                navigationSelectItem.LevelsOption);
        }
示例#7
0
        string BuildSqlQueryCmd(ExpandedNavigationSelectItem expanded, string condition)
        {
            string table = string.Format("[{0}]", expanded.NavigationSource.Name);
            string cmdSql = "select {0} {1} from {2} {3} {4} {5} {6}";
            string top = string.Empty;
            string skip = string.Empty;
            string fetch = string.Empty;

            if (!expanded.CountOption.HasValue && expanded.TopOption.HasValue)
            {
                if (expanded.SkipOption.HasValue)
                {
                    skip = string.Format("OFFSET {0} ROWS", expanded.SkipOption.Value); ;
                    fetch = string.Format("FETCH NEXT {0} ROWS ONLY", expanded.TopOption.Value);
                    top = string.Empty;
                }
                else
                    top = "top " + expanded.TopOption.Value;
            }

            var cmdtxt = string.Format(cmdSql
                , top
                , expanded.ParseSelect()
                , table
                , expanded.ParseWhere(condition, this.Model)
                , expanded.ParseOrderBy()
                , skip
                , fetch);
            return cmdtxt;
        }
 public static int GetPageSize(this ExpandedNavigationSelectItem navigationSelectItem)
 {
     return(navigationSelectItem.SelectAndExpand.GetPageSize());
 }
 public void EntitySetSetCorrectly()
 {
     ExpandedNavigationSelectItem expansion = new ExpandedNavigationSelectItem(new ODataExpandPath(new NavigationPropertySegment(HardCodedTestModel.GetPersonMyDogNavProp(), null)), HardCodedTestModel.GetDogsSet(), null);
     expansion.NavigationSource.Should().Be(HardCodedTestModel.GetDogsSet());
 }
示例#10
0
        // Process $levels in ExpandedNavigationSelectItem.
        private ExpandedNavigationSelectItem ProcessLevels(
            ExpandedNavigationSelectItem expandItem,
            int levelsMaxLiteralExpansionDepth,
            out bool levelsEncounteredInExpand,
            out bool isMaxLevelInExpand)
        {
            int level;

            isMaxLevelInExpand = false;

            // $level=x
            if (expandItem.LevelsOption != null && !expandItem.LevelsOption.IsMaxLevel)
            {
                levelsEncounteredInExpand = true;
                level = (int)expandItem.LevelsOption.Level;
                if (LevelsMaxLiteralExpansionDepth < 0)
                {
                    levelsMaxLiteralExpansionDepth = level;
                }
            }
            else
            {
                if (levelsMaxLiteralExpansionDepth < 0)
                {
                    levelsMaxLiteralExpansionDepth = ODataValidationSettings.DefaultMaxExpansionDepth;
                }

                if (expandItem.LevelsOption == null)
                {
                    // no $level
                    levelsEncounteredInExpand = false;
                    level = 1;
                }
                else
                {
                    // $level=max
                    levelsEncounteredInExpand = true;
                    isMaxLevelInExpand        = true;
                    level = levelsMaxLiteralExpansionDepth;
                }
            }

            // Do not expand when:
            // 1. $levels is equal to or less than 0.
            // 2. $levels value is greater than current MaxExpansionDepth
            if (level <= 0 || level > levelsMaxLiteralExpansionDepth)
            {
                return(null);
            }

            ExpandedNavigationSelectItem item = null;
            SelectExpandClause           currentSelectExpandClause = null;
            SelectExpandClause           selectExpandClause        = null;
            bool levelsEncounteredInInnerExpand = false;
            bool isMaxLevelInInnerExpand        = false;

            // Try diffent expansion depth until expandItem.SelectAndExpand is successfully expanded
            while (selectExpandClause == null && level > 0)
            {
                selectExpandClause = ProcessLevels(
                    expandItem.SelectAndExpand,
                    levelsMaxLiteralExpansionDepth - level,
                    out levelsEncounteredInInnerExpand,
                    out isMaxLevelInInnerExpand);
                level--;
            }

            if (selectExpandClause == null)
            {
                return(null);
            }

            // Correct level value
            level++;

            var    entityType = expandItem.NavigationSource.EntityType();
            string alreadyExpandedNavigationSourceName =
                (expandItem.PathToNavigationProperty.LastSegment as NavigationPropertySegment).NavigationProperty.Name;
            IEnumerable <SelectItem> autoExpandNavigationSelectItems = GetAutoExpandedNavigationSelectItems(
                entityType,
                Context.Model,
                alreadyExpandedNavigationSourceName,
                expandItem.NavigationSource,
                selectExpandClause.AllSelected);
            bool hasAutoExpandInExpand = (autoExpandNavigationSelectItems.Count() != 0);

            while (level > 0)
            {
                if (item == null)
                {
                    if (hasAutoExpandInExpand)
                    {
                        currentSelectExpandClause = new SelectExpandClause(
                            new SelectItem[] { }.Concat(selectExpandClause.SelectedItems)
                            .Concat(autoExpandNavigationSelectItems),
                            selectExpandClause.AllSelected);
                    }
                    else
                    {
                        currentSelectExpandClause = selectExpandClause;
                    }
                }
                else if (selectExpandClause.AllSelected)
                {
                    // Concat the processed items
                    currentSelectExpandClause = new SelectExpandClause(
                        new SelectItem[] { item }.Concat(selectExpandClause.SelectedItems)
                        .Concat(autoExpandNavigationSelectItems),
                        selectExpandClause.AllSelected);
                }
                else
                {
                    // PathSelectItem is needed for the expanded item if AllSelected is false.
                    PathSelectItem pathSelectItem = new PathSelectItem(
                        new ODataSelectPath(expandItem.PathToNavigationProperty));

                    // Keep default SelectItems before expanded item to keep consistent with normal SelectExpandClause
                    SelectItem[] items = new SelectItem[] { item, pathSelectItem };
                    currentSelectExpandClause = new SelectExpandClause(
                        new SelectItem[] { }.Concat(selectExpandClause.SelectedItems)
                        .Concat(items)
                        .Concat(autoExpandNavigationSelectItems),
                        selectExpandClause.AllSelected);
                }

                // Construct a new ExpandedNavigationSelectItem with current SelectExpandClause.
                item = new ExpandedNavigationSelectItem(
                    expandItem.PathToNavigationProperty,
                    expandItem.NavigationSource,
                    currentSelectExpandClause);

                level--;

                // Need expand and construct selectExpandClause every time if it is max level in inner expand
                if (isMaxLevelInInnerExpand)
                {
                    selectExpandClause = ProcessLevels(
                        expandItem.SelectAndExpand,
                        levelsMaxLiteralExpansionDepth - level,
                        out levelsEncounteredInInnerExpand,
                        out isMaxLevelInInnerExpand);
                }
            }

            levelsEncounteredInExpand = levelsEncounteredInExpand || levelsEncounteredInInnerExpand || hasAutoExpandInExpand;
            isMaxLevelInExpand        = isMaxLevelInExpand || isMaxLevelInInnerExpand;

            return(item);
        }
 public void LevelsOptionSetCorrectly()
 {
     LevelsClause levels = new LevelsClause(false, 16384);
     ExpandedNavigationSelectItem expansion = new ExpandedNavigationSelectItem(new ODataExpandPath(new NavigationPropertySegment(ModelBuildingHelpers.BuildValidNavigationProperty(), null)), HardCodedTestModel.GetPeopleSet(), null, null, null, null, null, null, null, levels);
     expansion.LevelsOption.IsMaxLevel.Should().BeFalse();
     expansion.LevelsOption.Level.Should().Be(16384);
 }
示例#12
0
        private static ODataUri GetCountODataUri(IEdmModel edmModel, OeEntryFactory entryFactory, ExpandedNavigationSelectItem item, Object value)
        {
            FilterClause?filterClause = GetFilter(edmModel, entryFactory, item, value);

            if (filterClause == null)
            {
                throw new InvalidOperationException("Cannot create count expression");
            }

            var entitytSet   = (IEdmEntitySet)((ResourceRangeVariable)filterClause.RangeVariable).NavigationSource;
            var pathSegments = new ODataPathSegment[] { new EntitySetSegment(entitytSet)
                                                        {
                                                            Identifier = entitytSet.Name
                                                        }, CountSegment.Instance };

            return(new ODataUri()
            {
                Filter = filterClause,
                Path = new ODataPath(pathSegments),
            });
        }
示例#13
0
 /// <summary>
 /// Handle an ExpandedNavigationSelectItem
 /// </summary>
 /// <param name="item">the item to Handle</param>
 public virtual void Handle(ExpandedNavigationSelectItem item)
 {
     throw new NotImplementedException();
 }
        // Process $levels in ExpandedNavigationSelectItem.
        private ExpandedNavigationSelectItem ProcessLevels(
            ExpandedNavigationSelectItem expandItem,
            int levelsMaxLiteralExpansionDepth,
            out bool levelsEncounteredInExpand,
            out bool isMaxLevelInExpand)
        {
            int level;
            isMaxLevelInExpand = false;

            // $level=x
            if (expandItem.LevelsOption != null && !expandItem.LevelsOption.IsMaxLevel)
            {
                levelsEncounteredInExpand = true;
                level = (int)expandItem.LevelsOption.Level;
                if (LevelsMaxLiteralExpansionDepth < 0)
                {
                    levelsMaxLiteralExpansionDepth = level;
                }
            }
            else
            {
                if (levelsMaxLiteralExpansionDepth < 0)
                {
                    levelsMaxLiteralExpansionDepth = ODataValidationSettings.DefaultMaxExpansionDepth;
                }

                if (expandItem.LevelsOption == null)
                {
                    // no $level
                    levelsEncounteredInExpand = false;
                    level = 1;
                }
                else
                {
                    // $level=max
                    levelsEncounteredInExpand = true;
                    isMaxLevelInExpand = true;
                    level = levelsMaxLiteralExpansionDepth;
                }
            }

            // Do not expand when:
            // 1. $levels is equal to or less than 0.
            // 2. $levels value is greater than current MaxExpansionDepth
            if (level <= 0 || level > levelsMaxLiteralExpansionDepth)
            {
                return null;
            }

            ExpandedNavigationSelectItem item = null;
            SelectExpandClause currentSelectExpandClause = null;
            SelectExpandClause selectExpandClause = null;
            bool levelsEncounteredInInnerExpand = false;
            bool isMaxLevelInInnerExpand = false;

            // Try diffent expansion depth until expandItem.SelectAndExpand is successfully expanded
            while (selectExpandClause == null && level > 0)
            {
                selectExpandClause = ProcessLevels(
                        expandItem.SelectAndExpand,
                        levelsMaxLiteralExpansionDepth - level,
                        out levelsEncounteredInInnerExpand,
                        out isMaxLevelInInnerExpand);
                level--;
            }

            if (selectExpandClause == null)
            {
                return null;
            }

            // Correct level value
            level++;

            var entityType = expandItem.NavigationSource.EntityType();
            string alreadyExpandedNavigationSourceName =
                (expandItem.PathToNavigationProperty.LastSegment as NavigationPropertySegment).NavigationProperty.Name;
            IEnumerable<SelectItem> autoExpandNavigationSelectItems = GetAutoExpandedNavigationSelectItems(
                entityType,
                Context.Model,
                alreadyExpandedNavigationSourceName, 
                expandItem.NavigationSource, 
                selectExpandClause.AllSelected);
            bool hasAutoExpandInExpand = (autoExpandNavigationSelectItems.Count() != 0);

            while (level > 0)
            {
                if (item == null)
                {
                    if (hasAutoExpandInExpand)
                    {
                        currentSelectExpandClause = new SelectExpandClause(
                            new SelectItem[] { }.Concat(selectExpandClause.SelectedItems)
                                .Concat(autoExpandNavigationSelectItems),
                            selectExpandClause.AllSelected);
                    }
                    else
                    {
                        currentSelectExpandClause = selectExpandClause;
                    }
                }
                else if (selectExpandClause.AllSelected)
                {
                    // Concat the processed items
                    currentSelectExpandClause = new SelectExpandClause(
                        new SelectItem[] { item }.Concat(selectExpandClause.SelectedItems)
                            .Concat(autoExpandNavigationSelectItems),
                        selectExpandClause.AllSelected);
                }
                else
                {
                    // PathSelectItem is needed for the expanded item if AllSelected is false. 
                    PathSelectItem pathSelectItem = new PathSelectItem(
                        new ODataSelectPath(expandItem.PathToNavigationProperty));

                    // Keep default SelectItems before expanded item to keep consistent with normal SelectExpandClause 
                    SelectItem[] items = new SelectItem[] { item, pathSelectItem };
                    currentSelectExpandClause = new SelectExpandClause(
                        new SelectItem[] { }.Concat(selectExpandClause.SelectedItems)
                            .Concat(items)
                            .Concat(autoExpandNavigationSelectItems),
                        selectExpandClause.AllSelected);
                }

                // Construct a new ExpandedNavigationSelectItem with current SelectExpandClause.
                item = new ExpandedNavigationSelectItem(
                    expandItem.PathToNavigationProperty,
                    expandItem.NavigationSource,
                    currentSelectExpandClause);

                level--;

                // Need expand and construct selectExpandClause every time if it is max level in inner expand
                if (isMaxLevelInInnerExpand) 
                {
                    selectExpandClause = ProcessLevels(
                        expandItem.SelectAndExpand,
                        levelsMaxLiteralExpansionDepth - level,
                        out levelsEncounteredInInnerExpand,
                        out isMaxLevelInInnerExpand);
                }
            }

            levelsEncounteredInExpand = levelsEncounteredInExpand || levelsEncounteredInInnerExpand || hasAutoExpandInExpand;
            isMaxLevelInExpand = isMaxLevelInExpand || isMaxLevelInInnerExpand;

            return item;
        }
        public void ExpandWithNestedQueryOptionsShouldWork()
        {
            var ervFilter = new EntityRangeVariable(ExpressionConstants.It, HardCodedTestModel.GetDogTypeReference(), HardCodedTestModel.GetDogsSet());
            var ervOrderby = new EntityRangeVariable(ExpressionConstants.It, HardCodedTestModel.GetDogTypeReference(), HardCodedTestModel.GetDogsSet());
            var expand =
                new ExpandedNavigationSelectItem(
                    new ODataExpandPath(new NavigationPropertySegment(HardCodedTestModel.GetPersonMyDogNavProp(), null)),
                    HardCodedTestModel.GetPeopleSet(),
                    null,
                    new FilterClause(
                        new BinaryOperatorNode(
                            BinaryOperatorKind.Equal,
                            new SingleValuePropertyAccessNode(new EntityRangeVariableReferenceNode("$it", ervFilter), HardCodedTestModel.GetDogColorProp()),
                            new ConstantNode("Brown", "'Brown'")),
                            ervFilter),
                    new OrderByClause(
                        null,
                        new SingleValuePropertyAccessNode(new EntityRangeVariableReferenceNode("$it", ervOrderby), HardCodedTestModel.GetDogColorProp()),
                        OrderByDirection.Ascending,
                        ervOrderby),
                    1,
                    /* skipOption */ null,
                    true,
                    new SearchClause(new SearchTermNode("termX")),
                    /* levelsOption*/ null);

            ODataUri uri = new ODataUri()
            {
                ServiceRoot = new Uri("http://gobbledygook/"),
                Path = new ODataPath(new EntitySetSegment(HardCodedTestModel.GetPeopleSet())),
                SelectAndExpand = new SelectExpandClause(new[] { expand }, true)
            };

            Uri actualUri = new ODataUriBuilder(ODataUrlConventions.Default, uri).BuildUri();
            Assert.Equal("http://gobbledygook/People?$expand=" + Uri.EscapeDataString("MyDog($filter=Color eq 'Brown';$orderby=Color;$top=1;$count=true;$search=termX)"), actualUri.OriginalString);
        }
示例#16
0
        /// <summary>
        /// Creates an instance of <see cref="ExpandSegment"/> based on the metadata in the given <see cref="ExpandedNavigationSelectItem"/>.
        /// </summary>
        /// <param name="expandItem">The metadata-bound expand segment to create the <see cref="ExpandSegment"/> from.</param>
        /// <param name="currentResourceType">The current resource type.</param>
        /// <returns>The created <see cref="ExpandSegment"/>.</returns>
        private ExpandSegment CreateExpandSegment(ExpandedNavigationSelectItem expandItem, ResourceType currentResourceType)
        {
            Debug.Assert(expandItem != null, "expandItem != null");
            Debug.Assert(currentResourceType != null, "currentResourceType != null");

            // pull the Resource* instances from annotations on the IEdm* instances.
            IEdmNavigationProperty navigationProperty = ((NavigationPropertySegment)expandItem.PathToNavigationProperty.LastSegment).NavigationProperty;
            ResourceProperty property = ((IResourcePropertyBasedEdmProperty)navigationProperty).ResourceProperty;
            Debug.Assert(property != null, "property != null");
            ResourceSetWrapper targetResourceSet = ((IResourceSetBasedEdmEntitySet)expandItem.NavigationSource).ResourceSet;
            Debug.Assert(targetResourceSet != null, "targetResourceSet != null");

            // Further scope the type based on type segments in the path.
            currentResourceType = this.GetTargetResourceTypeFromTypeSegments(expandItem.PathToNavigationProperty, currentResourceType);
            Debug.Assert(currentResourceType != null, "currentResourceType != null");

            // The expanded resource type may require higher response version. Update version of the response accordingly
            //
            // Note the response DSV is payload specific and since for GET we won't know what DSV the instances to be
            // serialized will require until serialization time which happens after the headers are written, 
            // the best we can do is to determine this at the set level.
            this.description.UpdateVersion(targetResourceSet, this.service);

            bool singleResult = property.Kind == ResourcePropertyKind.ResourceReference;
            DataServiceConfiguration.CheckResourceRightsForRead(targetResourceSet, singleResult);

            Expression filter = DataServiceConfiguration.ComposeQueryInterceptors(this.service.Instance, targetResourceSet);

            if (targetResourceSet.PageSize != 0 && !singleResult && !this.IsCustomPaged)
            {
                OrderingInfo internalOrderingInfo = new OrderingInfo(true);
                ParameterExpression p = Expression.Parameter(targetResourceSet.ResourceType.InstanceType, "p");
                foreach (var keyProp in targetResourceSet.GetKeyPropertiesForOrderBy())
                {
                    Expression e;
                    if (keyProp.CanReflectOnInstanceTypeProperty)
                    {
                        e = Expression.Property(p, targetResourceSet.ResourceType.GetPropertyInfo(keyProp));
                    }
                    else
                    {
                        // object LateBoundMethods.GetValue(object, ResourceProperty)
                        e = Expression.Call(
                                null, /*instance*/
                                DataServiceProviderMethods.GetValueMethodInfo, 
                                p,
                                Expression.Constant(keyProp));
                        e = Expression.Convert(e, keyProp.Type);
                    }

                    internalOrderingInfo.Add(new OrderingExpression(Expression.Lambda(e, p), true));
                }

                return new ExpandSegment(property.Name, filter, targetResourceSet.PageSize, targetResourceSet, currentResourceType, property, internalOrderingInfo);
            }

            if (!singleResult && this.IsCustomPaged)
            {
                // Expansion of collection could result in custom paging provider giving next link, so we need to set the null continuation token.
                this.CheckAndApplyCustomPaging(null);
            }

            return new ExpandSegment(property.Name, filter, this.service.Configuration.MaxResultsPerCollection, targetResourceSet, currentResourceType, property, null);
        }
 public void SearchOptionSetCorrectly()
 {
     SearchClause search = new SearchClause(new SearchTermNode("SearchMe"));
     ExpandedNavigationSelectItem expansion = new ExpandedNavigationSelectItem(new ODataExpandPath(new NavigationPropertySegment(ModelBuildingHelpers.BuildValidNavigationProperty(), null)), HardCodedTestModel.GetPeopleSet(), null, null, null, null, null, null, search, null);
     expansion.SearchOption.Expression.ShouldBeSearchTermNode("SearchMe");
 }
 public void CountQueryOptionSetCorrectly()
 {
     ExpandedNavigationSelectItem expansion = new ExpandedNavigationSelectItem(new ODataExpandPath(new NavigationPropertySegment(ModelBuildingHelpers.BuildValidNavigationProperty(), null)), HardCodedTestModel.GetPeopleSet(), null, null, null, null, null, true, null, null);
     expansion.CountOption.Should().BeTrue();
 }
 public void SelectExpandOptionSetCorrectly()
 {
     SelectExpandClause selectAndExpand = new SelectExpandClause(null, true);
     ExpandedNavigationSelectItem expansion = new ExpandedNavigationSelectItem(new ODataExpandPath(new NavigationPropertySegment(ModelBuildingHelpers.BuildValidNavigationProperty(), null)), HardCodedTestModel.GetPeopleSet(), selectAndExpand, null, null, null, null, null, null, null);
     expansion.SelectAndExpand.AllSelected.Should().BeTrue();
     expansion.SelectAndExpand.SelectedItems.Should().BeEmpty();
 }
 public void EntitySetCanBeNullInOptionConstructor()
 {
     ExpandedNavigationSelectItem expansion = new ExpandedNavigationSelectItem(new ODataExpandPath(new NavigationPropertySegment(ModelBuildingHelpers.BuildValidNavigationProperty(), null)), null, null, null, null, null, null, null, null, null);
     expansion.NavigationSource.Should().BeNull();
 }
示例#21
0
        internal Expression ProjectAsWrapper(Expression source, SelectExpandClause selectExpandClause, IEdmEntityType entityType, IEdmNavigationSource navigationSource, ExpandedNavigationSelectItem expandedItem = null)
        {
            Type elementType;

            if (source.Type.IsCollection(out elementType))
            {
                // new CollectionWrapper<ElementType> { Instance = source.Select(s => new Wrapper { ... }) };
                return(ProjectCollection(source, elementType, selectExpandClause, entityType, navigationSource, expandedItem));
            }
            else
            {
                // new Wrapper { v1 = source.property ... }
                return(ProjectElement(source, selectExpandClause, entityType, navigationSource));
            }
        }
示例#22
0
        private void BuildOrderBySkipTake(OeNavigationSelectItem navigationItem, OrderByClause orderByClause, bool hasSelectItems)
        {
            while (orderByClause != null)
            {
                var propertyNode = (SingleValuePropertyAccessNode)orderByClause.Expression;
                if (propertyNode.Source is SingleNavigationNode navigationNode)
                {
                    OeNavigationSelectItem?      match;
                    ExpandedNavigationSelectItem?navigationSelectItem = null;
                    for (; ;)
                    {
                        if ((match = navigationItem.FindHierarchyNavigationItem(navigationNode.NavigationProperty)) != null)
                        {
                            match.AddStructuralItem((IEdmStructuralProperty)propertyNode.Property, true);
                            break;
                        }

                        SelectExpandClause selectExpandClause;
                        if (navigationSelectItem == null)
                        {
                            var pathSelectItem = new PathSelectItem(new ODataSelectPath(new PropertySegment((IEdmStructuralProperty)propertyNode.Property)));
                            selectExpandClause = new SelectExpandClause(new[] { pathSelectItem }, false);
                        }
                        else
                        {
                            selectExpandClause = new SelectExpandClause(new[] { navigationSelectItem }, false);
                        }

                        var segment = new NavigationPropertySegment(navigationNode.NavigationProperty, navigationNode.NavigationSource);
                        navigationSelectItem = new ExpandedNavigationSelectItem(new ODataExpandPath(segment), navigationNode.NavigationSource, selectExpandClause);

                        if (navigationNode.Source is SingleNavigationNode singleNavigationNode)
                        {
                            navigationNode = singleNavigationNode;
                        }
                        else
                        {
                            break;
                        }
                    }

                    if (navigationSelectItem != null)
                    {
                        if (match == null)
                        {
                            match = navigationItem;
                        }

                        var selectItemTranslator = new OeSelectItemTranslator(_edmModel, true);
                        selectItemTranslator.Translate(match, navigationSelectItem);
                    }
                }
                else
                {
                    if (hasSelectItems)
                    {
                        navigationItem.AddStructuralItem((IEdmStructuralProperty)propertyNode.Property, true);
                    }
                }

                orderByClause = orderByClause.ThenBy;
            }
        }
示例#23
0
        private void GetAutoSelectExpandItems(IEdmEntityType baseEntityType, IEdmModel model, IEdmNavigationSource navigationSource, bool isAllSelected,
                                              ModelBoundQuerySettings modelBoundQuerySettings, int depth, out List <SelectItem> autoSelectItems, out List <SelectItem> autoExpandItems)
        {
            autoSelectItems = new List <SelectItem>();
            autoExpandItems = new List <SelectItem>();

            if (baseEntityType == null)
            {
                return;
            }

            IList <SelectModelPath> autoSelectProperties = model.GetAutoSelectPaths(baseEntityType, null, modelBoundQuerySettings);

            foreach (var autoSelectProperty in autoSelectProperties)
            {
                ODataSelectPath odataSelectPath = BuildSelectPath(autoSelectProperty, navigationSource);
                PathSelectItem  pathSelectItem  = new PathSelectItem(odataSelectPath);
                autoSelectItems.Add(pathSelectItem);
            }

            depth--;
            if (depth < 0)
            {
                return;
            }

            IList <ExpandModelPath> autoExpandNavigationProperties = model.GetAutoExpandPaths(baseEntityType, null, !isAllSelected, modelBoundQuerySettings);

            foreach (ExpandModelPath itemPath in autoExpandNavigationProperties)
            {
                string navigationPath = itemPath.NavigationPropertyPath;
                IEdmNavigationProperty navigationProperty = itemPath.Navigation;

                IEdmNavigationSource currentEdmNavigationSource;
                if (navigationPath != null)
                {
                    currentEdmNavigationSource = navigationSource.FindNavigationTarget(navigationProperty);
                }
                else
                {
                    currentEdmNavigationSource = navigationSource.FindNavigationTarget(navigationProperty, new EdmPathExpression(navigationPath));
                }

                if (currentEdmNavigationSource != null)
                {
                    ODataExpandPath expandPath = BuildExpandPath(itemPath, navigationSource, currentEdmNavigationSource);

                    SelectExpandClause           selectExpandClause = new SelectExpandClause(new List <SelectItem>(), true);
                    ExpandedNavigationSelectItem item = new ExpandedNavigationSelectItem(expandPath, currentEdmNavigationSource, selectExpandClause);
                    modelBoundQuerySettings = model.GetModelBoundQuerySettings(navigationProperty, navigationProperty.ToEntityType());
                    List <SelectItem> nestedSelectItems;
                    List <SelectItem> nestedExpandItems;

                    int maxExpandDepth = GetMaxExpandDepth(modelBoundQuerySettings, navigationProperty.Name);
                    if (maxExpandDepth != 0 && maxExpandDepth < depth)
                    {
                        depth = maxExpandDepth;
                    }

                    GetAutoSelectExpandItems(
                        currentEdmNavigationSource.EntityType(),
                        model,
                        item.NavigationSource,
                        true,
                        modelBoundQuerySettings,
                        depth,
                        out nestedSelectItems,
                        out nestedExpandItems);

                    selectExpandClause = new SelectExpandClause(nestedSelectItems.Concat(nestedExpandItems), nestedSelectItems.Count == 0);
                    item = new ExpandedNavigationSelectItem(expandPath, currentEdmNavigationSource, selectExpandClause);

                    autoExpandItems.Add(item);
                    if (!isAllSelected || autoSelectProperties.Any())
                    {
                        PathSelectItem pathSelectItem = new PathSelectItem(new ODataSelectPath(expandPath));
                        autoExpandItems.Add(pathSelectItem);
                    }
                }
            }
        }
示例#24
0
            private static Uri BuildNavigationNextPageLink(ODataResource entry, ExpandedNavigationSelectItem expandedNavigationSelectItem)
            {
                var segment = (NavigationPropertySegment)expandedNavigationSelectItem.PathToNavigationProperty.LastSegment;
                ResourceRangeVariableReferenceNode refNode            = OeGetParser.CreateRangeVariableReferenceNode((IEdmEntitySet)segment.NavigationSource);
                IEdmNavigationProperty             navigationProperty = segment.NavigationProperty;

                var keys = new List <KeyValuePair <IEdmStructuralProperty, Object> >();

                if (navigationProperty.IsPrincipal())
                {
                    IEnumerator <IEdmStructuralProperty> dependentProperties = navigationProperty.Partner.DependentProperties().GetEnumerator();
                    foreach (IEdmStructuralProperty key in navigationProperty.Partner.PrincipalProperties())
                    {
                        foreach (ODataProperty property in entry.Properties)
                        {
                            if (property.Name == key.Name)
                            {
                                dependentProperties.MoveNext();
                                keys.Add(new KeyValuePair <IEdmStructuralProperty, Object>(dependentProperties.Current, property.Value));
                                break;
                            }
                        }
                    }
                }
                else
                {
                    IEnumerator <IEdmStructuralProperty> principalProperties = navigationProperty.PrincipalProperties().GetEnumerator();
                    foreach (IEdmStructuralProperty key in navigationProperty.DependentProperties())
                    {
                        foreach (ODataProperty property in entry.Properties)
                        {
                            if (property.Name == key.Name)
                            {
                                principalProperties.MoveNext();
                                keys.Add(new KeyValuePair <IEdmStructuralProperty, Object>(principalProperties.Current, property.Value));
                                break;
                            }
                        }
                    }
                }

                BinaryOperatorNode filterExpression = OeGetParser.CreateFilterExpression(refNode, keys);

                if (expandedNavigationSelectItem.FilterOption != null)
                {
                    filterExpression = new BinaryOperatorNode(BinaryOperatorKind.And, filterExpression, expandedNavigationSelectItem.FilterOption.Expression);
                }

                var segments = new ODataPathSegment[] { new EntitySetSegment((IEdmEntitySet)refNode.NavigationSource) };

                var odataUri = new ODataUri()
                {
                    Path            = new ODataPath(segments),
                    Filter          = new FilterClause(filterExpression, refNode.RangeVariable),
                    OrderBy         = expandedNavigationSelectItem.OrderByOption,
                    SelectAndExpand = expandedNavigationSelectItem.SelectAndExpand,
                    Top             = expandedNavigationSelectItem.TopOption,
                    Skip            = expandedNavigationSelectItem.SkipOption,
                    QueryCount      = expandedNavigationSelectItem.CountOption
                };

                return(odataUri.BuildUri(ODataUrlKeyDelimiter.Parentheses));
            }
示例#25
0
        // Process $levels in ExpandedNavigationSelectItem.
        private ExpandedNavigationSelectItem ProcessLevels(
            ExpandedNavigationSelectItem expandItem,
            int levelsMaxLiteralExpansionDepth,
            ModelBoundQuerySettings querySettings,
            out bool levelsEncounteredInExpand,
            out bool isMaxLevelInExpand)
        {
            int level;

            isMaxLevelInExpand = false;

            if (expandItem.LevelsOption == null)
            {
                levelsEncounteredInExpand = false;
                level = 1;
            }
            else
            {
                levelsEncounteredInExpand = true;
                if (expandItem.LevelsOption.IsMaxLevel)
                {
                    isMaxLevelInExpand = true;
                    level = levelsMaxLiteralExpansionDepth;
                }
                else
                {
                    level = (int)expandItem.LevelsOption.Level;
                }
            }

            // Do not expand when:
            // 1. $levels is equal to or less than 0.
            // 2. $levels value is greater than current MaxExpansionDepth
            if (level <= 0 || level > levelsMaxLiteralExpansionDepth)
            {
                return(null);
            }

            ExpandedNavigationSelectItem item = null;
            SelectExpandClause           currentSelectExpandClause = null;
            SelectExpandClause           selectExpandClause        = null;
            bool levelsEncounteredInInnerExpand = false;
            bool isMaxLevelInInnerExpand        = false;
            var  entityType = expandItem.NavigationSource.EntityType();
            IEdmNavigationProperty navigationProperty =
                (expandItem.PathToNavigationProperty.LastSegment as NavigationPropertySegment).NavigationProperty;
            ModelBoundQuerySettings nestQuerySettings = EdmLibHelpers.GetModelBoundQuerySettings(navigationProperty,
                                                                                                 navigationProperty.ToEntityType(),
                                                                                                 Context.Model);

            // Try different expansion depth until expandItem.SelectAndExpand is successfully expanded
            while (selectExpandClause == null && level > 0)
            {
                selectExpandClause = ProcessLevels(
                    expandItem.SelectAndExpand,
                    levelsMaxLiteralExpansionDepth - level,
                    nestQuerySettings,
                    out levelsEncounteredInInnerExpand,
                    out isMaxLevelInInnerExpand);
                level--;
            }

            if (selectExpandClause == null)
            {
                return(null);
            }

            // Correct level value
            level++;
            List <SelectItem> originAutoSelectItems;
            List <SelectItem> originAutoExpandItems;
            int maxDepth = GetMaxExpandDepth(querySettings, navigationProperty.Name);

            if (maxDepth == 0 || levelsMaxLiteralExpansionDepth > maxDepth)
            {
                maxDepth = levelsMaxLiteralExpansionDepth;
            }

            GetAutoSelectExpandItems(
                entityType,
                Context.Model,
                expandItem.NavigationSource,
                selectExpandClause.AllSelected,
                nestQuerySettings,
                maxDepth - 1,
                out originAutoSelectItems,
                out originAutoExpandItems);
            if (expandItem.SelectAndExpand.SelectedItems.Any(it => it is PathSelectItem))
            {
                originAutoSelectItems.Clear();
            }

            if (level > 1)
            {
                RemoveSameExpandItem(navigationProperty, originAutoExpandItems);
            }

            List <SelectItem> autoExpandItems = new List <SelectItem>(originAutoExpandItems);
            bool hasAutoSelectExpandInExpand  = (originAutoSelectItems.Count() + originAutoExpandItems.Count() != 0);
            bool allSelected       = originAutoSelectItems.Count == 0 && selectExpandClause.AllSelected;
            var  typeLevelSettings = EdmLibHelpers.GetModelBoundQuerySettings(entityType, this.Context.Model, this.Context.DefaultQuerySettings);
            bool allAutoSelected   = (typeLevelSettings != null && typeLevelSettings.DefaultSelectType == SelectExpandType.Automatic);

            while (level > 0)
            {
                autoExpandItems = RemoveExpandItemExceedMaxDepth(maxDepth - level, originAutoExpandItems);
                if (item == null)
                {
                    if (hasAutoSelectExpandInExpand)
                    {
                        currentSelectExpandClause = new SelectExpandClause(
                            new SelectItem[] { }.Concat(selectExpandClause.SelectedItems)
                            .Concat(originAutoSelectItems).Concat(autoExpandItems),
                            allSelected,
                            allAutoSelected);
                    }
                    else
                    {
                        currentSelectExpandClause = selectExpandClause;
                    }
                }
                else if (selectExpandClause.AllSelected)
                {
                    // Concat the processed items
                    currentSelectExpandClause = new SelectExpandClause(
                        new SelectItem[] { item }.Concat(selectExpandClause.SelectedItems)
                        .Concat(originAutoSelectItems).Concat(autoExpandItems),
                        allSelected,
                        allAutoSelected);
                }
                else
                {
                    // PathSelectItem is needed for the expanded item if AllSelected is false.
                    PathSelectItem pathSelectItem = new PathSelectItem(
                        new ODataSelectPath(expandItem.PathToNavigationProperty));

                    // Keep default SelectItems before expanded item to keep consistent with normal SelectExpandClause
                    SelectItem[] items = new SelectItem[] { item, pathSelectItem };
                    currentSelectExpandClause = new SelectExpandClause(
                        new SelectItem[] { }.Concat(selectExpandClause.SelectedItems)
                        .Concat(items)
                        .Concat(originAutoSelectItems).Concat(autoExpandItems),
                        allSelected,
                        allAutoSelected);
                }

                // Construct a new ExpandedNavigationSelectItem with current SelectExpandClause.
                item = new ExpandedNavigationSelectItem(
                    expandItem.PathToNavigationProperty,
                    expandItem.NavigationSource,
                    currentSelectExpandClause,
                    expandItem.FilterOption,
                    expandItem.OrderByOption,
                    expandItem.TopOption,
                    expandItem.SkipOption,
                    expandItem.CountOption,
                    expandItem.SearchOption,
                    null,
                    expandItem.ComputeOption,
                    expandItem.ApplyOption);

                level--;

                // Need expand and construct selectExpandClause every time if it is max level in inner expand
                if (isMaxLevelInInnerExpand)
                {
                    selectExpandClause = ProcessLevels(
                        expandItem.SelectAndExpand,
                        levelsMaxLiteralExpansionDepth - level,
                        nestQuerySettings,
                        out levelsEncounteredInInnerExpand,
                        out isMaxLevelInInnerExpand);
                }
            }

            levelsEncounteredInExpand = levelsEncounteredInExpand || levelsEncounteredInInnerExpand || hasAutoSelectExpandInExpand;
            isMaxLevelInExpand        = isMaxLevelInExpand || isMaxLevelInInnerExpand;

            return(item);
        }
        /// <summary>
        /// Handle an ExpandedNavigationSelectItem
        /// </summary>
        /// <param name="item">the item to Handle</param>
        public override void Handle(ExpandedNavigationSelectItem item)
        {
            var navigationProperty = (item.PathToNavigationProperty.LastSegment as NavigationPropertySegment).NavigationProperty;
            this.ExpandedChildElement = this.ParentElement.GetType().GetProperty(navigationProperty.Name).GetValue(this.ParentElement, null);

            if (this.ExpandedChildElement is IEnumerable)
            {
                var entityInstanceType = EdmClrTypeUtils.GetInstanceType(item.NavigationSource.EntityType().FullName());
                Expression resultExpression = (this.ExpandedChildElement as IEnumerable).AsQueryable().Expression;

                if (item.FilterOption != null)
                {
                    resultExpression = resultExpression.ApplyFilter(entityInstanceType, null, item.FilterOption);
                }

                if (item.SearchOption != null)
                {
                    resultExpression = resultExpression.ApplySearch(entityInstanceType, null, item.SearchOption);
                }

                if (item.OrderByOption != null)
                {
                    resultExpression = resultExpression.ApplyOrderBy(entityInstanceType, null, item.OrderByOption);
                }

                if (item.SkipOption.HasValue)
                {
                    resultExpression = resultExpression.ApplySkip(entityInstanceType, item.SkipOption.Value);
                }

                if (item.TopOption.HasValue)
                {
                    resultExpression = resultExpression.ApplyTop(entityInstanceType, item.TopOption.Value);
                }

                Expression<Func<object>> lambda = Expression.Lambda<Func<object>>(resultExpression);
                Func<object> compiled = lambda.Compile();
                this.ExpandedChildElement = compiled() as IEnumerable;
            }
        }
示例#27
0
        public void NavPropSetCorrectly()
        {
            ExpandedNavigationSelectItem expansion = new ExpandedNavigationSelectItem(new ODataExpandPath(new NavigationPropertySegment(HardCodedTestModel.GetPersonMyDogNavProp(), null)), HardCodedTestModel.GetPeopleSet(), null);

            expansion.PathToNavigationProperty.FirstSegment.ShouldBeNavigationPropertySegment(HardCodedTestModel.GetPersonMyDogNavProp());
        }
        private void ValidateRestrictions(
            int?remainDepth,
            int currentDepth,
            SelectExpandClause selectExpandClause,
            IEdmNavigationProperty navigationProperty,
            ODataValidationSettings validationSettings)
        {
            IEdmModel edmModel = _selectExpandQueryOption.Context.Model;
            int?      depth    = remainDepth;

            if (remainDepth < 0)
            {
                throw new ODataException(
                          Error.Format(SRResources.MaxExpandDepthExceeded, currentDepth - 1, "MaxExpansionDepth"));
            }

            IEdmProperty       pathProperty;
            IEdmStructuredType pathStructuredType;

            if (navigationProperty == null)
            {
                pathProperty       = _selectExpandQueryOption.Context.TargetProperty;
                pathStructuredType = _selectExpandQueryOption.Context.TargetStructuredType;
            }
            else
            {
                pathProperty       = navigationProperty;
                pathStructuredType = navigationProperty.ToEntityType();
            }

            foreach (SelectItem selectItem in selectExpandClause.SelectedItems)
            {
                ExpandedNavigationSelectItem expandItem = selectItem as ExpandedNavigationSelectItem;
                if (expandItem != null)
                {
                    NavigationPropertySegment navigationSegment =
                        (NavigationPropertySegment)expandItem.PathToNavigationProperty.LastSegment;
                    IEdmNavigationProperty property = navigationSegment.NavigationProperty;
                    if (EdmHelpers.IsNotExpandable(property, edmModel))
                    {
                        throw new ODataException(Error.Format(SRResources.NotExpandablePropertyUsedInExpand,
                                                              property.Name));
                    }

                    if (edmModel != null)
                    {
                        ValidateOtherQueryOptionInExpand(property, edmModel, expandItem, validationSettings);
                        bool isExpandable;
                        ExpandConfiguration expandConfiguration;
                        isExpandable = EdmHelpers.IsExpandable(property.Name,
                                                               pathProperty,
                                                               pathStructuredType,
                                                               edmModel,
                                                               out expandConfiguration);
                        if (isExpandable)
                        {
                            int maxDepth = expandConfiguration.MaxDepth;
                            if (maxDepth > 0 && (remainDepth == null || maxDepth < remainDepth))
                            {
                                remainDepth = maxDepth;
                            }
                        }
                        else if (!isExpandable)
                        {
                            if (!_defaultQuerySettings.EnableExpand ||
                                (expandConfiguration != null && expandConfiguration.ExpandType == SelectExpandType.Disabled))
                            {
                                throw new ODataException(Error.Format(SRResources.NotExpandablePropertyUsedInExpand,
                                                                      property.Name));
                            }
                        }
                    }

                    if (remainDepth.HasValue)
                    {
                        remainDepth--;
                        if (expandItem.LevelsOption != null)
                        {
                            ValidateLevelsOption(expandItem.LevelsOption, remainDepth.Value, currentDepth + 1, edmModel,
                                                 property);
                        }
                    }

                    ValidateRestrictions(remainDepth, currentDepth + 1, expandItem.SelectAndExpand, property,
                                         validationSettings);
                    remainDepth = depth;
                }

                ValidateSelectItem(selectItem, pathProperty, pathStructuredType, edmModel);
            }
        }
示例#29
0
        public void SkipOptionSetCorrectly()
        {
            ExpandedNavigationSelectItem expansion = new ExpandedNavigationSelectItem(new ODataExpandPath(new NavigationPropertySegment(ModelBuildingHelpers.BuildValidNavigationProperty(), null)), HardCodedTestModel.GetPeopleSet(), null, null, null, 42, null, null, null, null);

            expansion.SkipOption.Should().Be(42);
        }
示例#30
0
文件: SQL2008.cs 项目: maskx/OData
        string BuildSqlQueryCmd(ExpandedNavigationSelectItem expanded, string condition)
        {
            string table = string.Format("[{0}]", expanded.NavigationSource.Name);
            string cmdTxt = string.Empty;

            if (!expanded.CountOption.HasValue && expanded.TopOption.HasValue)
            {
                if (expanded.SkipOption.HasValue)
                {
                    cmdTxt = string.Format(
            @"select t.* from(
            select ROW_NUMBER() over ({0}) as rowIndex,{1} from {2} {3}
            ) as t
            where t.rowIndex between {4} and {5}"
                     , expanded.ParseOrderBy()
                     , expanded.ParseSelect()
                     , table
                     , expanded.ParseWhere(condition, this.Model)
                     , expanded.SkipOption.Value + 1
                     , expanded.SkipOption.Value + expanded.TopOption.Value);
                }
                else
                    cmdTxt = string.Format("select top {0} {1} from {2} {3} {4}"
                       , expanded.TopOption.Value
                       , expanded.ParseSelect()
                       , table
                       , expanded.ParseWhere(condition, this.Model)
                       , expanded.ParseOrderBy());

            }
            else
            {
                cmdTxt = string.Format("select  {0}  from {1} {2} {3} "
                         , expanded.ParseSelect()
                         , table
                         , expanded.ParseWhere(condition, this.Model)
                         , expanded.ParseOrderBy());
            }

            return cmdTxt;
        }
 public void NavPropSetCorrectly()
 {
     ExpandedNavigationSelectItem expansion = new ExpandedNavigationSelectItem(new ODataExpandPath(new NavigationPropertySegment(HardCodedTestModel.GetPersonMyDogNavProp(), null)), HardCodedTestModel.GetPeopleSet(), null);
     expansion.PathToNavigationProperty.FirstSegment.ShouldBeNavigationPropertySegment(HardCodedTestModel.GetPersonMyDogNavProp());
 }
示例#32
0
        private void GetAutoSelectExpandItems(
            IEdmEntityType baseEntityType,
            IEdmModel model,
            IEdmNavigationSource navigationSource,
            bool isAllSelected,
            ModelBoundQuerySettings modelBoundQuerySettings,
            int depth,
            out List <SelectItem> autoSelectItems,
            out List <SelectItem> autoExpandItems)
        {
            autoSelectItems = new List <SelectItem>();
            var autoSelectProperties = EdmLibHelpers.GetAutoSelectProperties(null,
                                                                             baseEntityType, model, modelBoundQuerySettings);

            foreach (var autoSelectProperty in autoSelectProperties)
            {
                List <ODataPathSegment> pathSegments = new List <ODataPathSegment>()
                {
                    new PropertySegment(autoSelectProperty)
                };

                PathSelectItem pathSelectItem = new PathSelectItem(
                    new ODataSelectPath(pathSegments));
                autoSelectItems.Add(pathSelectItem);
            }

            autoExpandItems = new List <SelectItem>();
            depth--;
            if (depth < 0)
            {
                return;
            }

            var autoExpandNavigationProperties = EdmLibHelpers.GetAutoExpandNavigationProperties(null, baseEntityType,
                                                                                                 model, !isAllSelected, modelBoundQuerySettings);

            foreach (var navigationProperty in autoExpandNavigationProperties)
            {
                IEdmNavigationSource currentEdmNavigationSource =
                    navigationSource.FindNavigationTarget(navigationProperty);

                if (currentEdmNavigationSource != null)
                {
                    List <ODataPathSegment> pathSegments = new List <ODataPathSegment>()
                    {
                        new NavigationPropertySegment(navigationProperty, currentEdmNavigationSource)
                    };

                    ODataExpandPath    expandPath         = new ODataExpandPath(pathSegments);
                    SelectExpandClause selectExpandClause = new SelectExpandClause(new List <SelectItem>(),
                                                                                   true);
                    ExpandedNavigationSelectItem item = new ExpandedNavigationSelectItem(expandPath,
                                                                                         currentEdmNavigationSource, selectExpandClause);
                    modelBoundQuerySettings = EdmLibHelpers.GetModelBoundQuerySettings(navigationProperty,
                                                                                       navigationProperty.ToEntityType(), model);
                    List <SelectItem> nestedSelectItems;
                    List <SelectItem> nestedExpandItems;

                    int maxExpandDepth = GetMaxExpandDepth(modelBoundQuerySettings, navigationProperty.Name);
                    if (maxExpandDepth != 0 && maxExpandDepth < depth)
                    {
                        depth = maxExpandDepth;
                    }

                    GetAutoSelectExpandItems(
                        currentEdmNavigationSource.EntityType(),
                        model,
                        item.NavigationSource,
                        true,
                        modelBoundQuerySettings,
                        depth,
                        out nestedSelectItems,
                        out nestedExpandItems);

                    selectExpandClause = new SelectExpandClause(nestedSelectItems.Concat(nestedExpandItems),
                                                                nestedSelectItems.Count == 0);
                    item = new ExpandedNavigationSelectItem(expandPath, currentEdmNavigationSource,
                                                            selectExpandClause);

                    autoExpandItems.Add(item);
                    if (!isAllSelected || autoSelectProperties.Count() != 0)
                    {
                        PathSelectItem pathSelectItem = new PathSelectItem(
                            new ODataSelectPath(pathSegments));
                        autoExpandItems.Add(pathSelectItem);
                    }
                }
            }
        }
        public void ProjectAsWrapper_ProjectionContainsExpandedProperties()
        {
            // Arrange
            Order order = new Order();
            ExpandedNavigationSelectItem expandItem = new ExpandedNavigationSelectItem(
                new ODataExpandPath(new NavigationPropertySegment(_model.Order.NavigationProperties().Single(), navigationSource: _model.Customers)),
                _model.Customers,
                selectExpandOption: null);
            SelectExpandClause selectExpand = new SelectExpandClause(new SelectItem[] { expandItem }, allSelected: true);
            Expression source = Expression.Constant(order);
            _model.Model.SetAnnotationValue(_model.Order, new DynamicPropertyDictionaryAnnotation(typeof(Order).GetProperty("OrderProperties")));

            // Act
            Expression projection = _binder.ProjectAsWrapper(source, selectExpand, _model.Order);

            // Assert
            SelectExpandWrapper<Order> projectedOrder = Expression.Lambda(projection).Compile().DynamicInvoke() as SelectExpandWrapper<Order>;
            Assert.NotNull(projectedOrder);
            Assert.Contains("Customer", projectedOrder.Container.ToDictionary(new IdentityPropertyMapper()).Keys);
        }
示例#34
0
        public void EntitySetCanBeNullInOptionConstructor()
        {
            ExpandedNavigationSelectItem expansion = new ExpandedNavigationSelectItem(new ODataExpandPath(new NavigationPropertySegment(ModelBuildingHelpers.BuildValidNavigationProperty(), null)), null, null, null, null, null, null, null, null, null);

            expansion.NavigationSource.Should().BeNull();
        }
        // Process $levels in ExpandedNavigationSelectItem.
        private static ExpandedNavigationSelectItem ProcessLevels(
            ExpandedNavigationSelectItem expandItem,
            int levelsMaxLiteralExpansionDepth,
            out bool levelsEncounteredInExpand)
        {
            // Call ProcessLevels on SelectExpandClause recursively.
            SelectExpandClause selectExpandClause = ProcessLevels(
                expandItem.SelectAndExpand,
                levelsMaxLiteralExpansionDepth - 1,
                out levelsEncounteredInExpand);

            if (expandItem.LevelsOption == null)
            {
                if (levelsEncounteredInExpand)
                {
                    return new ExpandedNavigationSelectItem(
                        expandItem.PathToNavigationProperty,
                        expandItem.NavigationSource,
                        selectExpandClause);
                }
                else
                {
                    // Return the original ExpandedNavigationSelectItem if no $levels is found.
                    return expandItem;
                }
            }

            // There is $levels in current ExpandedNavigationSelectItem.
            levelsEncounteredInExpand = true;
            int level = expandItem.LevelsOption.IsMaxLevel ?
                levelsMaxLiteralExpansionDepth :
                (int)expandItem.LevelsOption.Level;

            if (level <= 0)
            {
                // Do not expand if $levels is equal to 0.
                return null;
            }

            // Initialize current SelectExpandClause with processed SelectExpandClause.
            SelectExpandClause currentSelectExpandClause = selectExpandClause;
            ExpandedNavigationSelectItem item = null;

            // Construct new ExpandedNavigationSelectItem with recursive expansion.
            while (level > 0)
            {
                // Construct a new ExpandedNavigationSelectItem with current SelectExpandClause.
                item = new ExpandedNavigationSelectItem(
                    expandItem.PathToNavigationProperty,
                    expandItem.NavigationSource,
                    currentSelectExpandClause);

                // Update current SelectExpandClause with the new ExpandedNavigationSelectItem.
                if (selectExpandClause.AllSelected)
                {
                    currentSelectExpandClause = new SelectExpandClause(
                        new[] { item }.Concat(selectExpandClause.SelectedItems),
                        selectExpandClause.AllSelected);
                }
                else
                {
                    // PathSelectItem is needed for the expanded item if AllSelected is false. 
                    PathSelectItem pathSelectItem = new PathSelectItem(
                        new ODataSelectPath(expandItem.PathToNavigationProperty));
                    currentSelectExpandClause = new SelectExpandClause(
                        new SelectItem[] { item, pathSelectItem }.Concat(selectExpandClause.SelectedItems),
                        selectExpandClause.AllSelected);
                }

                level--;
            }

            return item;
        }
示例#36
0
        public void EntitySetSetCorrectly()
        {
            ExpandedNavigationSelectItem expansion = new ExpandedNavigationSelectItem(new ODataExpandPath(new NavigationPropertySegment(HardCodedTestModel.GetPersonMyDogNavProp(), null)), HardCodedTestModel.GetDogsSet(), null);

            expansion.NavigationSource.Should().Be(HardCodedTestModel.GetDogsSet());
        }
        private static IEnumerable<SelectItem> GetAutoExpandedNavigationSelectItems(
            IEdmEntityType baseEntityType, 
            IEdmModel model,
            string alreadyExpandedNavigationSourceName,
            IEdmNavigationSource navigationSource,
            bool isAllSelected,
            bool searchDerivedTypeWhenAutoExpand)
        {
            var expandItems = new List<SelectItem>();
            var autoExpandNavigationProperties = EdmLibHelpers.GetAutoExpandNavigationProperties(baseEntityType, model,
                searchDerivedTypeWhenAutoExpand);
            foreach (var navigationProperty in autoExpandNavigationProperties)
            {
                if (!alreadyExpandedNavigationSourceName.Equals(navigationProperty.Name))
                {
                    IEdmEntityType entityType = navigationProperty.DeclaringEntityType();
                    IEdmNavigationSource currentEdmNavigationSource =
                        navigationSource.FindNavigationTarget(navigationProperty);

                    if (currentEdmNavigationSource != null)
                    {
                        List<ODataPathSegment> pathSegments = new List<ODataPathSegment>()
                        {
                            new NavigationPropertySegment(navigationProperty, currentEdmNavigationSource)
                        };

                        ODataExpandPath expandPath = new ODataExpandPath(pathSegments);
                        SelectExpandClause selectExpandClause = new SelectExpandClause(new List<SelectItem>(),
                            true);
                        ExpandedNavigationSelectItem item = new ExpandedNavigationSelectItem(expandPath,
                            currentEdmNavigationSource, selectExpandClause);
                        if (!currentEdmNavigationSource.EntityType().Equals(entityType))
                        {
                            IEnumerable<SelectItem> nestedSelectItems = GetAutoExpandedNavigationSelectItems(
                                currentEdmNavigationSource.EntityType(),
                                model,
                                alreadyExpandedNavigationSourceName,
                                item.NavigationSource,
                                true,
                                searchDerivedTypeWhenAutoExpand);
                            selectExpandClause = new SelectExpandClause(nestedSelectItems, true);
                            item = new ExpandedNavigationSelectItem(expandPath, currentEdmNavigationSource,
                                selectExpandClause);
                        }

                        expandItems.Add(item);
                        if (!isAllSelected)
                        {
                            PathSelectItem pathSelectItem = new PathSelectItem(
                                new ODataSelectPath(pathSegments));
                            expandItems.Add(pathSelectItem);
                        }
                    }
                }
            }
            return expandItems;
        }
示例#38
0
        // Process $levels in ExpandedNavigationSelectItem.
        private static ExpandedNavigationSelectItem ProcessLevels(
            ExpandedNavigationSelectItem expandItem,
            int levelsMaxLiteralExpansionDepth,
            out bool levelsEncounteredInExpand,
            out bool isMaxLevelInExpand)
        {
            int level;

            isMaxLevelInExpand = false;

            if (expandItem.LevelsOption == null)
            {
                levelsEncounteredInExpand = false;
                level = 1;
            }
            else
            {
                levelsEncounteredInExpand = true;
                if (expandItem.LevelsOption.IsMaxLevel)
                {
                    isMaxLevelInExpand = true;
                    level = levelsMaxLiteralExpansionDepth;
                }
                else
                {
                    level = (int)expandItem.LevelsOption.Level;
                }
            }

            // Do not expand when:
            // 1. $levels is equal to or less than 0.
            // 2. $levels value is greater than current MaxExpansionDepth
            if (level <= 0 || level > levelsMaxLiteralExpansionDepth)
            {
                return(null);
            }

            ExpandedNavigationSelectItem item = null;
            SelectExpandClause           currentSelectExpandClause = null;
            SelectExpandClause           selectExpandClause        = null;
            bool levelsEncounteredInInnerExpand = false;
            bool isMaxLevelInInnerExpand        = false;

            // Try diffent expansion depth until expandItem.SelectAndExpand is successfully expanded
            while (selectExpandClause == null && level > 0)
            {
                selectExpandClause = ProcessLevels(
                    expandItem.SelectAndExpand,
                    levelsMaxLiteralExpansionDepth - level,
                    out levelsEncounteredInInnerExpand,
                    out isMaxLevelInInnerExpand);
                level--;
            }

            if (selectExpandClause == null)
            {
                return(null);
            }

            // Correct level value
            level++;

            while (level > 0)
            {
                if (item == null)
                {
                    currentSelectExpandClause = selectExpandClause;
                }
                else if (selectExpandClause.AllSelected)
                {
                    // Concat the processed items
                    currentSelectExpandClause = new SelectExpandClause(
                        new SelectItem[] { item }.Concat(selectExpandClause.SelectedItems),
                        selectExpandClause.AllSelected);
                }
                else
                {
                    // PathSelectItem is needed for the expanded item if AllSelected is false.
                    PathSelectItem pathSelectItem = new PathSelectItem(
                        new ODataSelectPath(expandItem.PathToNavigationProperty));

                    // Keep default SelectItems before expanded item to keep consistent with normal SelectExpandClause
                    SelectItem[] items = new SelectItem[] { item, pathSelectItem };
                    currentSelectExpandClause = new SelectExpandClause(
                        new SelectItem[] { }.Concat(selectExpandClause.SelectedItems).Concat(items),
                        selectExpandClause.AllSelected);
                }

                // Construct a new ExpandedNavigationSelectItem with current SelectExpandClause.
                item = new ExpandedNavigationSelectItem(
                    expandItem.PathToNavigationProperty,
                    expandItem.NavigationSource,
                    currentSelectExpandClause);

                level--;

                // Need expand and construct selectExpandClause every time if it is max level in inner expand
                if (isMaxLevelInInnerExpand)
                {
                    selectExpandClause = ProcessLevels(
                        expandItem.SelectAndExpand,
                        levelsMaxLiteralExpansionDepth - level,
                        out levelsEncounteredInInnerExpand,
                        out isMaxLevelInInnerExpand);
                }
            }

            levelsEncounteredInExpand = levelsEncounteredInExpand || levelsEncounteredInInnerExpand;
            isMaxLevelInExpand        = isMaxLevelInExpand || isMaxLevelInInnerExpand;

            return(item);
        }
示例#39
0
        private void BuildExpansions(IEnumerable <SelectItem> selectedItems, HashSet <IEdmNavigationProperty> allNavigationProperties)
        {
            foreach (SelectItem selectItem in selectedItems)
            {
                ExpandedReferenceSelectItem expandReferenceItem = selectItem as ExpandedReferenceSelectItem;
                if (expandReferenceItem != null)
                {
                    ValidatePathIsSupportedForExpand(expandReferenceItem.PathToNavigationProperty);
                    NavigationPropertySegment navigationSegment  = (NavigationPropertySegment)expandReferenceItem.PathToNavigationProperty.LastSegment;
                    IEdmNavigationProperty    navigationProperty = navigationSegment.NavigationProperty;

                    int propertyCountInPath =
                        expandReferenceItem.PathToNavigationProperty.OfType <PropertySegment>().Count();

                    bool numberOfPropertiesInPathMatch =
                        (propertyCountInPath > 0 && PropertiesInPath != null &&
                         PropertiesInPath.Count == propertyCountInPath) || propertyCountInPath < 1;

                    if (numberOfPropertiesInPathMatch && allNavigationProperties.Contains(navigationProperty))
                    {
                        ExpandedNavigationSelectItem expandItem = selectItem as ExpandedNavigationSelectItem;
                        if (expandItem != null)
                        {
                            if (!ExpandedProperties.ContainsKey(navigationProperty))
                            {
                                ExpandedProperties.Add(navigationProperty, expandItem);
                            }
                            else
                            {
                                ExpandedProperties[navigationProperty] = expandItem;
                            }
                        }
                        else
                        {
                            ReferencedNavigationProperties.Add(navigationProperty);
                        }
                    }
                    else
                    {
                        //This is the case where the navigation property is not on the current type. We need to propagate the expand item to deeper SelectExpandNode.
                        IEdmStructuralProperty complexProperty = FindNextPropertySegment(expandReferenceItem.PathToNavigationProperty);

                        if (complexProperty != null)
                        {
                            SelectExpandClause newClause;
                            if (ExpandedPropertiesOnSubChildren.ContainsKey(complexProperty))
                            {
                                SelectExpandClause oldClause = ExpandedPropertiesOnSubChildren[complexProperty].SelectAndExpand;
                                newClause = new SelectExpandClause(
                                    oldClause.SelectedItems.Concat(new SelectItem[] { expandReferenceItem }), false);
                                ExpandedNavigationSelectItem newItem = new ExpandedNavigationSelectItem(expandReferenceItem.PathToNavigationProperty, navigationSegment.NavigationSource, newClause);
                                ExpandedPropertiesOnSubChildren[complexProperty] = newItem;
                            }
                            else
                            {
                                newClause = new SelectExpandClause(new SelectItem[] { expandReferenceItem }, false);
                                ExpandedNavigationSelectItem newItem = new ExpandedNavigationSelectItem(expandReferenceItem.PathToNavigationProperty, navigationSegment.NavigationSource, newClause);
                                ExpandedPropertiesOnSubChildren.Add(complexProperty, newItem);
                            }
                        }
                    }
                }
            }
        }
        // Process $levels in ExpandedNavigationSelectItem.
        private static ExpandedNavigationSelectItem ProcessLevels(
            ExpandedNavigationSelectItem expandItem,
            int levelsMaxLiteralExpansionDepth,
            out bool levelsEncounteredInExpand,
            out bool isMaxLevelInExpand)
        {
            int level;
            isMaxLevelInExpand = false;

            if (expandItem.LevelsOption == null)
            {
                levelsEncounteredInExpand = false;
                level = 1;
            }
            else
            {
                levelsEncounteredInExpand = true;
                if (expandItem.LevelsOption.IsMaxLevel)
                {
                    isMaxLevelInExpand = true;
                    level = levelsMaxLiteralExpansionDepth;
                }
                else
                {
                    level = (int)expandItem.LevelsOption.Level;
                }
            }

            // Do not expand when:
            // 1. $levels is equal to or less than 0.
            // 2. $levels value is greater than current MaxExpansionDepth
            if (level <= 0 || level > levelsMaxLiteralExpansionDepth)
            {
                return null;
            }

            ExpandedNavigationSelectItem item = null;
            SelectExpandClause currentSelectExpandClause = null;
            SelectExpandClause selectExpandClause = null;
            bool levelsEncounteredInInnerExpand = false;
            bool isMaxLevelInInnerExpand = false;

            // Try diffent expansion depth until expandItem.SelectAndExpand is successfully expanded
            while (selectExpandClause == null && level > 0)
            {
                selectExpandClause = ProcessLevels(
                        expandItem.SelectAndExpand,
                        levelsMaxLiteralExpansionDepth - level,
                        out levelsEncounteredInInnerExpand,
                        out isMaxLevelInInnerExpand);
                level--;
            }

            if (selectExpandClause == null)
            {
                return null;
            }

            // Correct level value
            level++;

            while (level > 0)
            {
                if (item == null)
                {
                    currentSelectExpandClause = selectExpandClause;
                }
                else if (selectExpandClause.AllSelected)
                {
                    // Concat the processed items
                    currentSelectExpandClause = new SelectExpandClause(
                        new SelectItem[] { item }.Concat(selectExpandClause.SelectedItems),
                        selectExpandClause.AllSelected);
                }
                else
                {
                    // PathSelectItem is needed for the expanded item if AllSelected is false. 
                    PathSelectItem pathSelectItem = new PathSelectItem(
                        new ODataSelectPath(expandItem.PathToNavigationProperty));

                    // Keep default SelectItems before expanded item to keep consistent with normal SelectExpandClause 
                    SelectItem[] items = new SelectItem[] { item, pathSelectItem };
                    currentSelectExpandClause = new SelectExpandClause(
                        new SelectItem[] { }.Concat(selectExpandClause.SelectedItems).Concat(items),
                        selectExpandClause.AllSelected);
                }

                // Construct a new ExpandedNavigationSelectItem with current SelectExpandClause.
                item = new ExpandedNavigationSelectItem(
                    expandItem.PathToNavigationProperty,
                    expandItem.NavigationSource,
                    currentSelectExpandClause);

                level--;

                // Need expand and construct selectExpandClause every time if it is max level in inner expand
                if (isMaxLevelInInnerExpand) 
                {
                    selectExpandClause = ProcessLevels(
                        expandItem.SelectAndExpand,
                        levelsMaxLiteralExpansionDepth - level,
                        out levelsEncounteredInInnerExpand,
                        out isMaxLevelInInnerExpand);
                }
            }

            levelsEncounteredInExpand = levelsEncounteredInExpand || levelsEncounteredInInnerExpand;
            isMaxLevelInExpand = isMaxLevelInExpand || isMaxLevelInInnerExpand;

            return item;
        }
示例#41
0
 public OeNavigationSelectItem(IEdmEntitySetBase entitySet, OeNavigationSelectItem parent, ExpandedNavigationSelectItem item, OeNavigationSelectItemKind kind)
     : this(entitySet, CreatePath(parent.Path, item.PathToNavigationProperty))
 {
     _edmProperty          = ((NavigationPropertySegment)item.PathToNavigationProperty.LastSegment).NavigationProperty;
     _navigationSelectItem = item;
     EntitySet             = entitySet;
     Kind   = kind;
     Parent = parent;
 }
示例#42
0
        private async Task WriteNavigationNextLink(OeEntryFactory parentEntryFactory, ExpandedNavigationSelectItem item, Object value)
        {
            Uri?nextPageLink = new OeNextPageLinkBuilder(_queryContext).GetNavigationUri(parentEntryFactory, item, value);

            if (nextPageLink == null)
            {
                return;
            }

            var  segment      = (NavigationPropertySegment)item.PathToNavigationProperty.LastSegment;
            bool isCollection = segment.NavigationProperty.Type.IsCollection();
            var  resourceInfo = new ODataNestedResourceInfo()
            {
                IsCollection = isCollection,
                Name         = segment.NavigationProperty.Name
            };
            await _writer.WriteStartAsync(resourceInfo).ConfigureAwait(false);

            if (isCollection)
            {
                var resourceSet = new ODataResourceSet()
                {
                    NextPageLink = nextPageLink
                };
                await _writer.WriteStartAsync(resourceSet).ConfigureAwait(false);

                await _writer.WriteEndAsync().ConfigureAwait(false);
            }
            else
            {
                resourceInfo.Url = nextPageLink;
            }

            await _writer.WriteEndAsync().ConfigureAwait(false);
        }
示例#43
0
        private static void HandleExpandedNavigationSelectItem(SelectStatement statement, ExpandedNavigationSelectItem item)
        {
            var property = item.PathToNavigationProperty.FirstSegment as NavigationPropertySegment;

            if (property != null)
            {
                var firstPart = property.NavigationProperty.Name;
                var newSelect = new SelectStatement(new List <string>());
                HandleItems(item.SelectAndExpand, newSelect);

                statement.Columns(newSelect.ColumnsList.Select(x => firstPart + "/" + x).ToArray());
            }
            else
            {
                throw new NotSupportedException(string.Format("ExpandedNavigationSelectItem type '{0}' is not supported.", item.PathToNavigationProperty.FirstSegment.GetType().FullName));
            }
        }
示例#44
0
        // new CollectionWrapper<ElementType> { Instance = source.Select((ElementType element) => new Wrapper { }) }
        private Expression ProjectCollection(Expression source, Type elementType, SelectExpandClause selectExpandClause, IEdmEntityType entityType, IEdmNavigationSource navigationSource, ExpandedNavigationSelectItem expandedItem)
        {
            ParameterExpression element = Expression.Parameter(elementType);

            // expression
            //      new Wrapper { }
            Expression projection = ProjectElement(element, selectExpandClause, entityType, navigationSource);

            // expression
            //      (ElementType element) => new Wrapper { }
            LambdaExpression selector = Expression.Lambda(projection, element);

            if (expandedItem != null)
            {
                source = AddOrderByQueryForSource(source, expandedItem.OrderByOption, elementType);
            }

            if (_settings.PageSize.HasValue ||
                (expandedItem != null && (expandedItem.TopOption.HasValue || expandedItem.SkipOption.HasValue)))
            {
                // nested paging. Need to apply order by first, and take one more than page size as we need to know
                // whether the collection was truncated or not while generating next page links.
                IEnumerable <IEdmStructuralProperty> properties =
                    entityType.Key().Any()
                        ? entityType.Key()
                        : entityType
                    .StructuralProperties()
                    .Where(property => property.Type.IsPrimitive()).OrderBy(property => property.Name);

                if (expandedItem == null || expandedItem.OrderByOption == null)
                {
                    bool alreadyOrdered = false;
                    foreach (var prop in properties)
                    {
                        source = ExpressionHelpers.OrderByPropertyExpression(source, prop.Name, elementType,
                                                                             alreadyOrdered);
                        if (!alreadyOrdered)
                        {
                            alreadyOrdered = true;
                        }
                    }
                }

                if (expandedItem != null && expandedItem.SkipOption.HasValue)
                {
                    Contract.Assert(expandedItem.SkipOption.Value <= Int32.MaxValue);
                    source = ExpressionHelpers.Skip(source, (int)expandedItem.SkipOption.Value, elementType,
                                                    _settings.EnableConstantParameterization);
                }

                if (expandedItem != null && expandedItem.TopOption.HasValue)
                {
                    Contract.Assert(expandedItem.TopOption.Value <= Int32.MaxValue);
                    source = ExpressionHelpers.Take(source, (int)expandedItem.TopOption.Value, elementType,
                                                    _settings.EnableConstantParameterization);
                }

                if (_settings.PageSize.HasValue)
                {
                    source = ExpressionHelpers.Take(source, _settings.PageSize.Value + 1, elementType,
                                                    _settings.EnableConstantParameterization);
                }
            }

            // expression
            //      source.Select((ElementType element) => new Wrapper { })
            Expression selectedExpresion = Expression.Call(GetSelectMethod(elementType, projection.Type), source, selector);

            if (_settings.HandleNullPropagation == HandleNullPropagationOption.True)
            {
                // source == null ? null : projectedCollection
                return(Expression.Condition(
                           test: Expression.Equal(source, Expression.Constant(null)),
                           ifTrue: Expression.Constant(null, selectedExpresion.Type),
                           ifFalse: selectedExpresion));
            }
            else
            {
                return(selectedExpresion);
            }
        }
示例#45
0
        /// <summary>
        /// Build the $expand item, it maybe $expand=nav, $expand=complex/nav, $expand=nav/$ref, etc.
        /// </summary>
        /// <param name="expandReferenceItem">The expanded reference select item.</param>
        /// <param name="currentLevelPropertiesInclude">The current properties to include at current level.</param>
        /// <param name="structuralTypeInfo">The structural type properties.</param>
        private void BuildExpandItem(ExpandedReferenceSelectItem expandReferenceItem,
                                     IDictionary <IEdmStructuralProperty, SelectExpandIncludedProperty> currentLevelPropertiesInclude,
                                     EdmStructuralTypeInfo structuralTypeInfo)
        {
            Contract.Assert(expandReferenceItem != null && expandReferenceItem.PathToNavigationProperty != null);
            Contract.Assert(currentLevelPropertiesInclude != null);
            Contract.Assert(structuralTypeInfo != null);

            // Verify and process the $expand=abc/xyz/nav.
            ODataExpandPath          expandPath = expandReferenceItem.PathToNavigationProperty;
            IList <ODataPathSegment> remainingSegments;
            ODataPathSegment         segment = expandPath.GetFirstNonTypeCastSegment(out remainingSegments);

            PropertySegment firstPropertySegment = segment as PropertySegment;

            if (firstPropertySegment != null)
            {
                // for example: $expand=abc/xyz/nav, the remaining segment can't be null
                // because at least the last navigation property segment is there.
                Contract.Assert(remainingSegments != null);

                if (structuralTypeInfo.IsStructuralPropertyDefined(firstPropertySegment.Property))
                {
                    SelectExpandIncludedProperty newPropertySelectItem;
                    if (!currentLevelPropertiesInclude.TryGetValue(firstPropertySegment.Property, out newPropertySelectItem))
                    {
                        newPropertySelectItem = new SelectExpandIncludedProperty(firstPropertySegment);
                        currentLevelPropertiesInclude[firstPropertySegment.Property] = newPropertySelectItem;
                    }

                    newPropertySelectItem.AddSubExpandItem(remainingSegments, expandReferenceItem);
                }
            }
            else
            {
                // for example: $expand=nav, or $expand=NS.SubType/nav, the navigation property segment should be the last segment.
                // So, the remaining segments should be null.
                Contract.Assert(remainingSegments == null);

                NavigationPropertySegment firstNavigationSegment = segment as NavigationPropertySegment;
                Contract.Assert(firstNavigationSegment != null);

                if (structuralTypeInfo.IsNavigationPropertyDefined(firstNavigationSegment.NavigationProperty))
                {
                    // It's not allowed to have mulitple navigation expanded or referenced.
                    // for example: "$expand=nav($top=2),nav($skip=3)" is not allowed and will be merged (or throw exception) at ODL side.
                    ExpandedNavigationSelectItem expanded = expandReferenceItem as ExpandedNavigationSelectItem;
                    if (expanded != null)
                    {
                        if (ExpandedProperties == null)
                        {
                            ExpandedProperties = new Dictionary <IEdmNavigationProperty, ExpandedNavigationSelectItem>();
                        }

                        ExpandedProperties[firstNavigationSegment.NavigationProperty] = expanded;
                    }
                    else
                    {
                        // $expand=..../nav/$ref
                        if (ReferencedProperties == null)
                        {
                            ReferencedProperties = new Dictionary <IEdmNavigationProperty, ExpandedReferenceSelectItem>();
                        }

                        ReferencedProperties[firstNavigationSegment.NavigationProperty] = expandReferenceItem;
                    }
                }
            }
        }
 /// <summary>
 /// Handle an ExpandedNavigationSelectItem
 /// </summary>
 /// <param name="item">the item to Handle</param>
 public virtual void Handle(ExpandedNavigationSelectItem item)
 {
     throw new NotImplementedException();
 }
        private void Translate(ExpandTransformationNode transformation)
        {
            ExpandedNavigationSelectItem expandedNavigation = transformation.ExpandClause.SelectedItems.Single() as ExpandedNavigationSelectItem;

            AppendExpandExpression(expandedNavigation);
        }
示例#48
0
        private Expression BuildPropertyContainer(IEdmEntityType elementType, Expression source,
                                                  Dictionary <IEdmNavigationProperty, ExpandedNavigationSelectItem> propertiesToExpand,
                                                  ISet <IEdmStructuralProperty> propertiesToInclude, ISet <IEdmStructuralProperty> autoSelectedProperties, bool isSelectingOpenTypeSegments)
        {
            IList <NamedPropertyExpression> includedProperties = new List <NamedPropertyExpression>();

            foreach (KeyValuePair <IEdmNavigationProperty, ExpandedNavigationSelectItem> kvp in propertiesToExpand)
            {
                IEdmNavigationProperty       propertyToExpand = kvp.Key;
                ExpandedNavigationSelectItem expandItem       = kvp.Value;
                SelectExpandClause           projection       = expandItem.SelectAndExpand;

                Expression propertyName  = CreatePropertyNameExpression(elementType, propertyToExpand, source);
                Expression propertyValue = CreatePropertyValueExpressionWithFilter(elementType, propertyToExpand, source,
                                                                                   expandItem.FilterOption);
                Expression nullCheck = Expression.Equal(propertyValue, Expression.Constant(null));

                Expression countExpression = CreateTotalCountExpression(propertyValue, expandItem);

                // projection can be null if the expanded navigation property is not further projected or expanded.
                if (projection != null)
                {
                    propertyValue = ProjectAsWrapper(propertyValue, projection, propertyToExpand.ToEntityType(), expandItem.NavigationSource as IEdmEntitySet);
                }

                NamedPropertyExpression propertyExpression = new NamedPropertyExpression(propertyName, propertyValue);
                if (projection != null)
                {
                    if (!propertyToExpand.Type.IsCollection())
                    {
                        propertyExpression.NullCheck = nullCheck;
                    }
                    else if (_settings.PageSize != null)
                    {
                        propertyExpression.PageSize = _settings.PageSize.Value;
                    }

                    propertyExpression.TotalCount  = countExpression;
                    propertyExpression.CountOption = expandItem.CountOption;
                }

                includedProperties.Add(propertyExpression);
            }

            foreach (IEdmStructuralProperty propertyToInclude in propertiesToInclude)
            {
                Expression propertyName  = CreatePropertyNameExpression(elementType, propertyToInclude, source);
                Expression propertyValue = CreatePropertyValueExpression(elementType, propertyToInclude, source);
                includedProperties.Add(new NamedPropertyExpression(propertyName, propertyValue));
            }

            foreach (IEdmStructuralProperty propertyToInclude in autoSelectedProperties)
            {
                Expression propertyName  = CreatePropertyNameExpression(elementType, propertyToInclude, source);
                Expression propertyValue = CreatePropertyValueExpression(elementType, propertyToInclude, source);
                includedProperties.Add(new NamedPropertyExpression(propertyName, propertyValue)
                {
                    AutoSelected = true
                });
            }

            if (isSelectingOpenTypeSegments)
            {
                var dynamicPropertyDictionary = EdmLibHelpers.GetDynamicPropertyDictionary(elementType, _model);

                Expression propertyName          = Expression.Constant(dynamicPropertyDictionary.Name);
                Expression propertyValue         = Expression.Property(source, dynamicPropertyDictionary.Name);
                Expression nullablePropertyValue = ExpressionHelpers.ToNullable(propertyValue);
                if (_settings.HandleNullPropagation == HandleNullPropagationOption.True)
                {
                    // source == null ? null : propertyValue
                    propertyValue = Expression.Condition(
                        test: Expression.Equal(source, Expression.Constant(value: null)),
                        ifTrue: Expression.Constant(value: null, type: propertyValue.Type.ToNullable()),
                        ifFalse: nullablePropertyValue);
                }
                else
                {
                    propertyValue = nullablePropertyValue;
                }

                includedProperties.Add(new NamedPropertyExpression(propertyName, propertyValue));
            }

            // create a property container that holds all these property names and values.
            return(PropertyContainer.CreatePropertyContainer(includedProperties));
        }
        public void ProjectAsWrapper_NonCollection_ProjectedValueNullAndHandleNullPropagationTrue()
        {
            // Arrange
            _settings.HandleNullPropagation = HandleNullPropagationOption.True;
            ExpandedNavigationSelectItem expandItem = new ExpandedNavigationSelectItem(
                new ODataExpandPath(new NavigationPropertySegment(_model.Order.NavigationProperties().Single(), entitySet: _model.Customers)),
                _model.Customers,
                selectExpandOption: null);
            SelectExpandClause selectExpand = new SelectExpandClause(new SelectItem[] { expandItem }, allSelected: true);
            Expression source = Expression.Constant(null, typeof(Order));

            // Act
            Expression projection = _binder.ProjectAsWrapper(source, selectExpand, _model.Order);

            // Assert
            SelectExpandWrapper<Order> projectedOrder = Expression.Lambda(projection).Compile().DynamicInvoke() as SelectExpandWrapper<Order>;
            Assert.NotNull(projectedOrder);
            Assert.Null(projectedOrder.Instance);
            Assert.Null(projectedOrder.Container.ToDictionary()["Customer"]);
        }
        private OeNavigationSelectItem AddOrGetNavigationItem(OeNavigationSelectItem parentNavigationItem, ExpandedNavigationSelectItem item, bool isExpand)
        {
            IEdmEntitySetBase entitySet = OeEdmClrHelper.GetEntitySet(_edmModel, item);

            OeNavigationSelectItemKind kind;

            if (_notSelected)
            {
                kind = OeNavigationSelectItemKind.NotSelected;
            }
            else if (item.SelectAndExpand.IsNextLink())
            {
                kind = OeNavigationSelectItemKind.NextLink;
            }
            else
            {
                kind = OeNavigationSelectItemKind.Normal;
            }

            var childNavigationSelectItem = new OeNavigationSelectItem(entitySet, parentNavigationItem, item, kind);

            return(parentNavigationItem.AddOrGetNavigationItem(childNavigationSelectItem, isExpand));
        }
        public void ProjectAsWrapper_NonCollection_ProjectedValueNullAndHandleNullPropagationFalse_Throws()
        {
            // Arrange
            _settings.HandleNullPropagation = HandleNullPropagationOption.False;
            ExpandedNavigationSelectItem expandItem = new ExpandedNavigationSelectItem(
                new ODataExpandPath(new NavigationPropertySegment(_model.Order.NavigationProperties().Single(), entitySet: _model.Customers)),
                _model.Customers,
                selectExpandOption: null);
            SelectExpandClause selectExpand = new SelectExpandClause(new SelectItem[] { expandItem }, allSelected: true);
            Expression source = Expression.Constant(null, typeof(Order));

            // Act
            Expression projection = _binder.ProjectAsWrapper(source, selectExpand, _model.Order);

            // Assert
            var e = Assert.Throws<TargetInvocationException>(
                () => Expression.Lambda(projection).Compile().DynamicInvoke());
            Assert.IsType<NullReferenceException>(e.InnerException);
        }
示例#52
0
        private static FilterClause?GetFilter(IEdmModel edmModel, OeEntryFactory entryFactory, ExpandedNavigationSelectItem item, Object value)
        {
            SingleValueNode filterExpression;
            ResourceRangeVariableReferenceNode refNode;

            var segment = (NavigationPropertySegment)item.PathToNavigationProperty.LastSegment;
            IEdmNavigationProperty navigationProperty = segment.NavigationProperty;

            if (navigationProperty.ContainsTarget)
            {
                ModelBuilder.ManyToManyJoinDescription joinDescription = edmModel.GetManyToManyJoinDescription(navigationProperty);
                navigationProperty = joinDescription.JoinNavigationProperty.Partner;

                IEdmEntitySet joinNavigationSource             = OeEdmClrHelper.GetEntitySet(edmModel, joinDescription.JoinNavigationProperty);
                ResourceRangeVariableReferenceNode joinRefNode = OeEdmClrHelper.CreateRangeVariableReferenceNode(joinNavigationSource, "d");

                IEdmEntitySet targetNavigationSource             = OeEdmClrHelper.GetEntitySet(edmModel, joinDescription.TargetNavigationProperty);
                ResourceRangeVariableReferenceNode targetRefNode = OeEdmClrHelper.CreateRangeVariableReferenceNode(targetNavigationSource);

                var anyNode = new AnyNode(new Collection <RangeVariable>()
                {
                    joinRefNode.RangeVariable, targetRefNode.RangeVariable
                }, joinRefNode.RangeVariable)
                {
                    Source = new CollectionNavigationNode(targetRefNode, joinDescription.TargetNavigationProperty.Partner, null),
                    Body   = OeExpressionHelper.CreateFilterExpression(joinRefNode, GetKeys(navigationProperty.PrincipalProperties(), navigationProperty.DependentProperties()))
                };

                refNode          = targetRefNode;
                filterExpression = anyNode;
            }
            else
            {
                IEnumerable <IEdmStructuralProperty> parentKeys;
                IEnumerable <IEdmStructuralProperty> childKeys;
                if (navigationProperty.IsPrincipal())
                {
                    parentKeys = navigationProperty.Partner.PrincipalProperties();
                    childKeys  = navigationProperty.Partner.DependentProperties();
                }
                else
                {
                    if (navigationProperty.Type.IsCollection())
                    {
                        parentKeys = navigationProperty.PrincipalProperties();
                        childKeys  = navigationProperty.DependentProperties();
                    }
                    else
                    {
                        parentKeys = navigationProperty.DependentProperties();
                        childKeys  = navigationProperty.PrincipalProperties();
                    }
                }

                refNode = OeEdmClrHelper.CreateRangeVariableReferenceNode((IEdmEntitySetBase)segment.NavigationSource);
                List <KeyValuePair <IEdmStructuralProperty, Object> > keys = GetKeys(parentKeys, childKeys);
                if (IsNullKeys(keys))
                {
                    return(null);
                }

                filterExpression = OeExpressionHelper.CreateFilterExpression(refNode, keys);
            }

            if (item.FilterOption != null)
            {
                filterExpression = new BinaryOperatorNode(BinaryOperatorKind.And, filterExpression, item.FilterOption.Expression);
            }

            return(new FilterClause(filterExpression, refNode.RangeVariable));

            List <KeyValuePair <IEdmStructuralProperty, Object> > GetKeys(IEnumerable <IEdmStructuralProperty> parentKeys, IEnumerable <IEdmStructuralProperty> childKeys)
            {
                var keys = new List <KeyValuePair <IEdmStructuralProperty, Object> >();
                IEnumerator <IEdmStructuralProperty> childKeyEnumerator = childKeys.GetEnumerator();

                foreach (IEdmStructuralProperty parentKey in parentKeys)
                {
                    childKeyEnumerator.MoveNext();
                    Object keyValue = entryFactory.GetAccessorByName(parentKey.Name).GetValue(value);
                    keys.Add(new KeyValuePair <IEdmStructuralProperty, Object>(childKeyEnumerator.Current, keyValue));
                }
                return(keys);
            }
        public void ProjectAsWrapper_NullExpandedProperty_HasNullValueInProjectedWrapper()
        {
            // Arrange
            Order order = new Order();
            ExpandedNavigationSelectItem expandItem = new ExpandedNavigationSelectItem(
                new ODataExpandPath(new NavigationPropertySegment(_model.Order.NavigationProperties().Single(), entitySet: _model.Customers)),
                _model.Customers,
                selectExpandOption: null);
            SelectExpandClause selectExpand = new SelectExpandClause(new SelectItem[] { expandItem }, allSelected: true);
            Expression source = Expression.Constant(order);

            // Act
            Expression projection = _binder.ProjectAsWrapper(source, selectExpand, _model.Order);

            // Assert
            SelectExpandWrapper<Order> projectedOrder = Expression.Lambda(projection).Compile().DynamicInvoke() as SelectExpandWrapper<Order>;
            Assert.NotNull(projectedOrder);
            Assert.Contains("Customer", projectedOrder.Container.ToDictionary().Keys);
            Assert.Null(projectedOrder.Container.ToDictionary()["Customer"]);
        }
        // Process $levels in ExpandedNavigationSelectItem.
        private static ExpandedNavigationSelectItem ProcessLevels(
            ExpandedNavigationSelectItem expandItem,
            int levelsMaxLiteralExpansionDepth,
            out bool levelsEncounteredInExpand)
        {
            // Call ProcessLevels on SelectExpandClause recursively.
            SelectExpandClause selectExpandClause = ProcessLevels(
                expandItem.SelectAndExpand,
                levelsMaxLiteralExpansionDepth - 1,
                out levelsEncounteredInExpand);

            if (expandItem.LevelsOption == null)
            {
                if (levelsEncounteredInExpand)
                {
                    return(new ExpandedNavigationSelectItem(
                               expandItem.PathToNavigationProperty,
                               expandItem.NavigationSource,
                               selectExpandClause));
                }
                else
                {
                    // Return the original ExpandedNavigationSelectItem if no $levels is found.
                    return(expandItem);
                }
            }

            // There is $levels in current ExpandedNavigationSelectItem.
            levelsEncounteredInExpand = true;
            int level = expandItem.LevelsOption.IsMaxLevel ?
                        levelsMaxLiteralExpansionDepth :
                        (int)expandItem.LevelsOption.Level;

            if (level <= 0)
            {
                // Do not expand if $levels is equal to 0.
                return(null);
            }

            // Initialize current SelectExpandClause with processed SelectExpandClause.
            SelectExpandClause           currentSelectExpandClause = selectExpandClause;
            ExpandedNavigationSelectItem item = null;

            // Construct new ExpandedNavigationSelectItem with recursive expansion.
            while (level > 0)
            {
                // Construct a new ExpandedNavigationSelectItem with current SelectExpandClause.
                item = new ExpandedNavigationSelectItem(
                    expandItem.PathToNavigationProperty,
                    expandItem.NavigationSource,
                    currentSelectExpandClause);

                // Update current SelectExpandClause with the new ExpandedNavigationSelectItem.
                if (selectExpandClause.AllSelected)
                {
                    currentSelectExpandClause = new SelectExpandClause(
                        new[] { item }.Concat(selectExpandClause.SelectedItems),
                        selectExpandClause.AllSelected);
                }
                else
                {
                    // PathSelectItem is needed for the expanded item if AllSelected is false.
                    PathSelectItem pathSelectItem = new PathSelectItem(
                        new ODataSelectPath(expandItem.PathToNavigationProperty));
                    currentSelectExpandClause = new SelectExpandClause(
                        new SelectItem[] { item, pathSelectItem }.Concat(selectExpandClause.SelectedItems),
                        selectExpandClause.AllSelected);
                }

                level--;
            }

            return(item);
        }
        /// <summary>
        /// Writes ExpandItem node to string
        /// </summary>
        /// <param name="node">Node to write to string</param>
        /// <returns>String representation of node.</returns>
        private static string ToString(ExpandedNavigationSelectItem node)
        {
            if (node != null)
            {
                var expandItemString = "Expanded Navigation Property" +
                    tabHelper.Indent(() =>
                    {
                        string text = tabHelper.Prefix + ToString(node.PathToNavigationProperty);
                        // Include when we add V4 support
                        ////if (node.TopOption != null) expandItemString += tabHelper.Prefix + string.Format("TopOption({0})", node.TopOption);
                        ////if (node.SkipOption != null) expandItemString += tabHelper.Prefix + string.Format("SkipOption({0})", node.SkipOption);
                        ////if (node.InlineCountOption != null) expandItemString += tabHelper.Prefix + string.Format("InlineCountOption({0})", node.InlineCountOption);
                        if (node.FilterOption != null) text += ToString(node.FilterOption);
                        if (node.OrderByOption != null) text += ToString(node.OrderByOption);
                        if (node.SearchOption != null) text += ToString(node.SearchOption);
                        if (node.SelectAndExpand != null) text += ToString(node.SelectAndExpand);

                        return text;
                    });

                return expandItemString;
            }

            return String.Empty;
        }