public void ApplyTo_OnSingleEntity_WithUnTypedContext_Throws_InvalidOperation() { // Arrange CustomersModelWithInheritance model = new CustomersModelWithInheritance(); ODataQueryContext context = new ODataQueryContext(model.Model, model.Customer); SelectExpandQueryOption selectExpand = new SelectExpandQueryOption(select: "ID", expand: null, context: context); object entity = new object(); // Act & Assert Assert.Throws<NotSupportedException>(() => selectExpand.ApplyTo(entity, new ODataQuerySettings()), "The query option is not bound to any CLR type. 'ApplyTo' is only supported with a query option bound to a CLR type."); }
public void Ctor_SetsProperty_RawExpand() { // Arrange string expandValue = "expand"; _model.Model.SetAnnotationValue<ClrTypeAnnotation>(_model.Customer, new ClrTypeAnnotation(typeof(Customer))); ODataQueryContext context = new ODataQueryContext(_model.Model, typeof(Customer)); // Act SelectExpandQueryOption result = new SelectExpandQueryOption(select: null, expand: expandValue, context: context); // Assert Assert.Equal(expandValue, result.RawExpand); }
public void Property_SelectExpandClause_WorksWithUnTypedContext() { // Arrange CustomersModelWithInheritance model = new CustomersModelWithInheritance(); ODataQueryContext context = new ODataQueryContext(model.Model, model.Customer); SelectExpandQueryOption selectExpand = new SelectExpandQueryOption(select: "ID", expand: null, context: context); // Act & Assert Assert.NotNull(selectExpand.SelectExpandClause); }
public void SelectExpandCaluse_ThrowsODataException_InvalidQuery(string select, string expand, string error) { // Arrange IEdmModel model = _model.Model; _model.Model.SetAnnotationValue<ClrTypeAnnotation>(_model.Customer, new ClrTypeAnnotation(typeof(Customer))); ODataQueryContext context = new ODataQueryContext(model, typeof(Customer)); SelectExpandQueryOption option = new SelectExpandQueryOption(select, expand, context); // Act Assert.Throws<ODataException>( () => option.SelectExpandClause.ToString(), error); }
public void SelectExpandClause_CanParse_ModelBuiltForQueryable(string select, string expand) { // Arrange HttpConfiguration config = new HttpConfiguration(); config.Services.Replace(typeof(IAssembliesResolver), new TestAssemblyResolver()); ODataConventionModelBuilder builder = new ODataConventionModelBuilder(new HttpConfiguration(), isQueryCompositionMode: true); builder.Entity<Customer>(); IEdmModel model = builder.GetEdmModel(); ODataQueryContext context = new ODataQueryContext(model, typeof(Customer)); SelectExpandQueryOption option = new SelectExpandQueryOption(select, expand, context); // Act & Assert Assert.DoesNotThrow(() => option.SelectExpandClause.ToString()); }
public void ProcessLevelsCorrectly_WithNestedLevels() { // Arrange var model = ODataLevelsTest.GetEdmModel(); var context = new ODataQueryContext( model, model.FindDeclaredType("System.Web.OData.Routing.LevelsEntity")); var selectExpand = new SelectExpandQueryOption( select: null, expand: "Parent($expand=DerivedAncestors($levels=2);$levels=max)", context: context); selectExpand.LevelsMaxLiteralExpansionDepth = 4; // Act SelectExpandClause clause = selectExpand.ProcessLevels(); // Assert Assert.True(clause.AllSelected); Assert.Equal(1, clause.SelectedItems.Count()); // Level 1 of Parent. var parent = Assert.IsType <ExpandedNavigationSelectItem>(clause.SelectedItems.Single()); Assert.Equal( "Parent", ((NavigationPropertySegment)parent.PathToNavigationProperty.FirstSegment).NavigationProperty.Name); Assert.Null(parent.LevelsOption); var clauseOfParent = parent.SelectAndExpand; Assert.True(clauseOfParent.AllSelected); Assert.Equal(2, clauseOfParent.SelectedItems.Count()); // Level 1 of DerivedAncestors. var derivedAncestors = Assert.Single(clauseOfParent.SelectedItems.OfType <ExpandedNavigationSelectItem>().Where( item => item.PathToNavigationProperty.FirstSegment is NavigationPropertySegment && ((NavigationPropertySegment)item.PathToNavigationProperty.FirstSegment).NavigationProperty.Name == "DerivedAncestors")); Assert.Null(derivedAncestors.LevelsOption); var clauseOfDerivedAncestors = derivedAncestors.SelectAndExpand; Assert.True(clauseOfDerivedAncestors.AllSelected); Assert.Equal(1, clauseOfDerivedAncestors.SelectedItems.Count()); // Level 2 of DerivedAncestors. derivedAncestors = Assert.IsType <ExpandedNavigationSelectItem>(clauseOfDerivedAncestors.SelectedItems.Single()); Assert.Equal( "DerivedAncestors", ((NavigationPropertySegment)derivedAncestors.PathToNavigationProperty.FirstSegment).NavigationProperty.Name); Assert.Null(derivedAncestors.LevelsOption); clauseOfDerivedAncestors = derivedAncestors.SelectAndExpand; Assert.True(clauseOfDerivedAncestors.AllSelected); Assert.Equal(0, clauseOfDerivedAncestors.SelectedItems.Count()); // Level 2 of Parent. parent = Assert.Single(clauseOfParent.SelectedItems.OfType <ExpandedNavigationSelectItem>().Where( item => item.PathToNavigationProperty.FirstSegment is NavigationPropertySegment && ((NavigationPropertySegment)item.PathToNavigationProperty.FirstSegment).NavigationProperty.Name == "Parent")); Assert.Null(parent.LevelsOption); clauseOfParent = parent.SelectAndExpand; Assert.True(clauseOfParent.AllSelected); Assert.Equal(1, clauseOfParent.SelectedItems.Count()); // Level 1 of DerivedAncestors. derivedAncestors = Assert.Single(clauseOfParent.SelectedItems.OfType <ExpandedNavigationSelectItem>().Where( item => item.PathToNavigationProperty.FirstSegment is NavigationPropertySegment && ((NavigationPropertySegment)item.PathToNavigationProperty.FirstSegment).NavigationProperty.Name == "DerivedAncestors")); Assert.Null(derivedAncestors.LevelsOption); clauseOfDerivedAncestors = derivedAncestors.SelectAndExpand; Assert.True(clauseOfDerivedAncestors.AllSelected); Assert.Equal(1, clauseOfDerivedAncestors.SelectedItems.Count()); // Level 2 of DerivedAncestors. derivedAncestors = Assert.IsType <ExpandedNavigationSelectItem>(clauseOfDerivedAncestors.SelectedItems.Single()); Assert.Equal( "DerivedAncestors", ((NavigationPropertySegment)derivedAncestors.PathToNavigationProperty.FirstSegment).NavigationProperty.Name); Assert.Null(derivedAncestors.LevelsOption); clauseOfDerivedAncestors = derivedAncestors.SelectAndExpand; Assert.True(clauseOfDerivedAncestors.AllSelected); Assert.Equal(0, clauseOfDerivedAncestors.SelectedItems.Count()); }
public void ProcessLevelsCorrectly_WithMultipleProperties() { // Arrange var model = ODataLevelsTest.GetEdmModel(); var context = new ODataQueryContext( model, model.FindDeclaredType("System.Web.OData.Routing.LevelsEntity")); var selectExpand = new SelectExpandQueryOption( select: null, expand: "Parent($expand=Parent($levels=max),DerivedAncestors($levels=2;$select=ID)),BaseEntities($levels=2)", context: context); selectExpand.LevelsMaxLiteralExpansionDepth = 3; // Act SelectExpandClause clause = selectExpand.ProcessLevels(); // Assert Assert.True(clause.AllSelected); Assert.Equal(2, clause.SelectedItems.Count()); // Top level Parent. var parent = Assert.Single(clause.SelectedItems.OfType <ExpandedNavigationSelectItem>().Where( item => item.PathToNavigationProperty.FirstSegment is NavigationPropertySegment && ((NavigationPropertySegment)item.PathToNavigationProperty.FirstSegment).NavigationProperty.Name == "Parent")); Assert.Null(parent.LevelsOption); var clauseOfParent = parent.SelectAndExpand; Assert.True(clauseOfParent.AllSelected); Assert.Equal(2, clauseOfParent.SelectedItems.Count()); // Level 1 of inline Parent. var inlineParent = Assert.Single(clauseOfParent.SelectedItems.OfType <ExpandedNavigationSelectItem>().Where( item => item.PathToNavigationProperty.FirstSegment is NavigationPropertySegment && ((NavigationPropertySegment)item.PathToNavigationProperty.FirstSegment).NavigationProperty.Name == "Parent")); Assert.Null(inlineParent.LevelsOption); // Level 2 of inline Parent. var inlineParentClause = inlineParent.SelectAndExpand; Assert.True(inlineParentClause.AllSelected); Assert.Equal(1, inlineParentClause.SelectedItems.Count()); inlineParent = Assert.IsType <ExpandedNavigationSelectItem>(inlineParentClause.SelectedItems.Single()); Assert.Equal( "Parent", ((NavigationPropertySegment)inlineParent.PathToNavigationProperty.FirstSegment).NavigationProperty.Name); Assert.Null(inlineParent.LevelsOption); inlineParentClause = inlineParent.SelectAndExpand; Assert.True(inlineParentClause.AllSelected); Assert.Equal(0, inlineParentClause.SelectedItems.Count()); // Level 1 of inline DerivedAncestors. var inlineDerivedAncestors = Assert.Single(clauseOfParent.SelectedItems.OfType <ExpandedNavigationSelectItem>().Where( item => item.PathToNavigationProperty.FirstSegment is NavigationPropertySegment && ((NavigationPropertySegment)item.PathToNavigationProperty.FirstSegment).NavigationProperty.Name == "DerivedAncestors")); Assert.Null(inlineDerivedAncestors.LevelsOption); // Level 2 of inline DerivedAncestors. var inlineDerivedAncestorsClause = inlineDerivedAncestors.SelectAndExpand; Assert.False(inlineDerivedAncestorsClause.AllSelected); Assert.Equal(3, inlineDerivedAncestorsClause.SelectedItems.Count()); var idItem = Assert.Single(inlineDerivedAncestorsClause.SelectedItems.OfType <PathSelectItem>().Where( item => item.SelectedPath.FirstSegment is PropertySegment)); Assert.Equal("ID", ((PropertySegment)idItem.SelectedPath.FirstSegment).Property.Name); var derivedAncestorsItem = Assert.Single(inlineDerivedAncestorsClause.SelectedItems.OfType <PathSelectItem>().Where( item => item.SelectedPath.FirstSegment is NavigationPropertySegment)); Assert.Equal( "DerivedAncestors", ((NavigationPropertySegment)derivedAncestorsItem.SelectedPath.FirstSegment).NavigationProperty.Name); inlineDerivedAncestors = Assert.Single(inlineDerivedAncestorsClause.SelectedItems.OfType <ExpandedNavigationSelectItem>()); Assert.Equal( "DerivedAncestors", ((NavigationPropertySegment)inlineDerivedAncestors.PathToNavigationProperty.FirstSegment).NavigationProperty.Name); Assert.Null(inlineDerivedAncestors.LevelsOption); inlineDerivedAncestorsClause = inlineDerivedAncestors.SelectAndExpand; Assert.False(inlineDerivedAncestorsClause.AllSelected); Assert.Equal(1, inlineDerivedAncestorsClause.SelectedItems.Count()); idItem = Assert.Single(inlineDerivedAncestorsClause.SelectedItems.OfType <PathSelectItem>()); Assert.Equal("ID", ((PropertySegment)idItem.SelectedPath.FirstSegment).Property.Name); // Level 1 of BaseEntities. var baseEntities = Assert.Single(clause.SelectedItems.OfType <ExpandedNavigationSelectItem>().Where( item => item.PathToNavigationProperty.FirstSegment is NavigationPropertySegment && ((NavigationPropertySegment)item.PathToNavigationProperty.FirstSegment).NavigationProperty.Name == "BaseEntities")); Assert.Null(baseEntities.LevelsOption); // Level 2 of BaseEntities. var baseEntitiesClause = baseEntities.SelectAndExpand; Assert.True(baseEntitiesClause.AllSelected); Assert.Equal(1, baseEntitiesClause.SelectedItems.Count()); baseEntities = Assert.IsType <ExpandedNavigationSelectItem>(baseEntitiesClause.SelectedItems.Single()); Assert.Equal( "BaseEntities", ((NavigationPropertySegment)baseEntities.PathToNavigationProperty.FirstSegment).NavigationProperty.Name); Assert.Null(baseEntities.LevelsOption); baseEntitiesClause = baseEntities.SelectAndExpand; Assert.True(baseEntitiesClause.AllSelected); Assert.Equal(0, baseEntitiesClause.SelectedItems.Count()); }
public void ProcessLevelsCorrectly_NotAllSelected() { // Arrange var model = ODataLevelsTest.GetEdmModel(); var context = new ODataQueryContext( model, model.FindDeclaredType("System.Web.OData.Routing.LevelsEntity")); var selectExpand = new SelectExpandQueryOption( select: "Name", expand: "Parent($select=ID;$levels=max)", context: context); // Act SelectExpandClause clause = selectExpand.ProcessLevels(); // Assert // Level 1. Assert.False(clause.AllSelected); Assert.Equal(3, clause.SelectedItems.Count()); var nameSelectItem = Assert.Single(clause.SelectedItems.OfType <PathSelectItem>().Where( item => item.SelectedPath.FirstSegment is PropertySegment)); Assert.Equal("Name", ((PropertySegment)nameSelectItem.SelectedPath.FirstSegment).Property.Name); var parentSelectItem = Assert.Single(clause.SelectedItems.OfType <PathSelectItem>().Where( item => item.SelectedPath.FirstSegment is NavigationPropertySegment)); Assert.Equal( "Parent", ((NavigationPropertySegment)parentSelectItem.SelectedPath.FirstSegment).NavigationProperty.Name); var expandedItem = Assert.Single(clause.SelectedItems.OfType <ExpandedNavigationSelectItem>()); Assert.Equal( "Parent", ((NavigationPropertySegment)expandedItem.PathToNavigationProperty.FirstSegment).NavigationProperty.Name); Assert.Null(expandedItem.LevelsOption); // Level 2. clause = expandedItem.SelectAndExpand; Assert.False(clause.AllSelected); Assert.Equal(3, clause.SelectedItems.Count()); var idSelectItem = Assert.Single(clause.SelectedItems.OfType <PathSelectItem>().Where( item => item.SelectedPath.FirstSegment is PropertySegment)); Assert.Equal("ID", ((PropertySegment)idSelectItem.SelectedPath.FirstSegment).Property.Name); parentSelectItem = Assert.Single(clause.SelectedItems.OfType <PathSelectItem>().Where( item => item.SelectedPath.FirstSegment is NavigationPropertySegment)); Assert.Equal( "Parent", ((NavigationPropertySegment)parentSelectItem.SelectedPath.FirstSegment).NavigationProperty.Name); expandedItem = Assert.Single(clause.SelectedItems.OfType <ExpandedNavigationSelectItem>()); Assert.Equal( "Parent", ((NavigationPropertySegment)expandedItem.PathToNavigationProperty.FirstSegment).NavigationProperty.Name); Assert.Null(expandedItem.LevelsOption); clause = expandedItem.SelectAndExpand; Assert.False(clause.AllSelected); Assert.Equal(1, clause.SelectedItems.Count()); idSelectItem = Assert.IsType <PathSelectItem>(clause.SelectedItems.Single()); Assert.Equal("ID", ((PropertySegment)idSelectItem.SelectedPath.FirstSegment).Property.Name); }
public void ProcessLevelsCorrectly_AllSelected() { // Arrange var model = ODataLevelsTest.GetEdmModel(); var context = new ODataQueryContext( model, model.FindDeclaredType("System.Web.OData.Routing.LevelsEntity")); var selectExpand = new SelectExpandQueryOption( select: null, expand: "Parent($expand=Parent($levels=2))", context: context); selectExpand.LevelsMaxLiteralExpansionDepth = 3; // Act SelectExpandClause clause = selectExpand.ProcessLevels(); // Assert // Level 1. Assert.True(clause.AllSelected); Assert.Equal(1, clause.SelectedItems.Count()); var item = Assert.IsType<ExpandedNavigationSelectItem>(clause.SelectedItems.Single()); Assert.Equal( "Parent", ((NavigationPropertySegment)item.PathToNavigationProperty.FirstSegment).NavigationProperty.Name); Assert.Null(item.LevelsOption); // Level 2. clause = item.SelectAndExpand; Assert.True(clause.AllSelected); Assert.Equal(1, clause.SelectedItems.Count()); item = Assert.IsType<ExpandedNavigationSelectItem>(clause.SelectedItems.Single()); Assert.Equal( "Parent", ((NavigationPropertySegment)item.PathToNavigationProperty.FirstSegment).NavigationProperty.Name); Assert.Null(item.LevelsOption); // Level 3. clause = item.SelectAndExpand; Assert.True(clause.AllSelected); Assert.Equal(1, clause.SelectedItems.Count()); item = Assert.IsType<ExpandedNavigationSelectItem>(clause.SelectedItems.Single()); Assert.Equal( "Parent", ((NavigationPropertySegment)item.PathToNavigationProperty.FirstSegment).NavigationProperty.Name); Assert.Null(item.LevelsOption); clause = item.SelectAndExpand; Assert.True(clause.AllSelected); Assert.Equal(0, clause.SelectedItems.Count()); }
private void BuildQueryOptions(IDictionary <string, string> queryParameters) { foreach (KeyValuePair <string, string> kvp in queryParameters) { switch (kvp.Key.ToLowerInvariant()) { case "$filter": ThrowIfEmpty(kvp.Value, "$filter"); RawValues.Filter = kvp.Value; Filter = new FilterQueryOption(kvp.Value, Context, _queryOptionParser); break; case "$orderby": ThrowIfEmpty(kvp.Value, "$orderby"); RawValues.OrderBy = kvp.Value; OrderBy = new OrderByQueryOption(kvp.Value, Context, _queryOptionParser); break; case "$top": ThrowIfEmpty(kvp.Value, "$top"); RawValues.Top = kvp.Value; Top = new TopQueryOption(kvp.Value, Context, _queryOptionParser); break; case "$skip": ThrowIfEmpty(kvp.Value, "$skip"); RawValues.Skip = kvp.Value; Skip = new SkipQueryOption(kvp.Value, Context, _queryOptionParser); break; case "$select": RawValues.Select = kvp.Value; break; case "$count": ThrowIfEmpty(kvp.Value, "$count"); RawValues.Count = kvp.Value; Count = new CountQueryOption(kvp.Value, Context, _queryOptionParser); break; case "$expand": RawValues.Expand = kvp.Value; break; case "$format": RawValues.Format = kvp.Value; break; case "$skiptoken": RawValues.SkipToken = kvp.Value; break; case "$deltatoken": RawValues.DeltaToken = kvp.Value; break; case "$apply": ThrowIfEmpty(kvp.Value, "$apply"); RawValues.Apply = kvp.Value; Apply = new ApplyQueryOption(kvp.Value, Context, _queryOptionParser); break; default: // we don't throw if we can't recognize the query break; } } if (RawValues.Select != null || RawValues.Expand != null) { SelectExpand = new SelectExpandQueryOption(RawValues.Select, RawValues.Expand, Context, _queryOptionParser); } if (ODataCountMediaTypeMapping.IsCountRequest(Request)) { Count = new CountQueryOption( "true", Context, new ODataQueryOptionParser( Context.Model, Context.ElementType, Context.NavigationSource, new Dictionary <string, string> { { "$count", "true" } })); } }
/// <summary> /// Initializes a new instance of the <see cref="ODataQueryOptions"/> class based on the incoming request and some metadata information from /// the <see cref="ODataQueryContext"/>. /// </summary> /// <param name="context">The <see cref="ODataQueryContext"/> which contains the <see cref="IEdmModel"/> and some type information.</param> /// <param name="request">The incoming request message.</param> public ODataQueryOptions(ODataQueryContext context, HttpRequestMessage request) { if (context == null) { throw Error.ArgumentNull("context"); } if (request == null) { throw Error.ArgumentNull("request"); } if (request.GetConfiguration() != null) { _assembliesResolver = request.GetConfiguration().Services.GetAssembliesResolver(); } // fallback to the default assemblies resolver if none available. _assembliesResolver = _assembliesResolver ?? new DefaultAssembliesResolver(); // remember the context and request Context = context; Request = request; // Parse the query from request Uri RawValues = new ODataRawQueryOptions(); IEnumerable <KeyValuePair <string, string> > queryParameters = request.GetQueryNameValuePairs(); IDictionary <string, string> queryOptions = queryParameters.ToDictionary(p => p.Key, p => p.Value); _queryOptionParser = new ODataQueryOptionParser(context.Model, context.ElementType, context.NavigationSource, queryOptions); foreach (KeyValuePair <string, string> kvp in queryParameters) { switch (kvp.Key) { case "$apply": ThrowIfEmpty(kvp.Value, "$apply"); RawValues.Apply = kvp.Value; Apply = new ApplyQueryOption(context, _queryOptionParser); break; case "aggregationWindowSize": _aggregationWindowSize = int.Parse(kvp.Value); break; case "$filter": ThrowIfEmpty(kvp.Value, "$filter"); RawValues.Filter = kvp.Value; Filter = new FilterQueryOption(kvp.Value, context, _queryOptionParser); break; case "$orderby": ThrowIfEmpty(kvp.Value, "$orderby"); RawValues.OrderBy = kvp.Value; OrderBy = new OrderByQueryOption(kvp.Value, context, _queryOptionParser); break; case "$top": ThrowIfEmpty(kvp.Value, "$top"); RawValues.Top = kvp.Value; Top = new TopQueryOption(kvp.Value, context, _queryOptionParser); break; case "$skip": ThrowIfEmpty(kvp.Value, "$skip"); RawValues.Skip = kvp.Value; Skip = new SkipQueryOption(kvp.Value, context, _queryOptionParser); break; case "$select": RawValues.Select = kvp.Value; break; case "$count": ThrowIfEmpty(kvp.Value, "$count"); RawValues.Count = kvp.Value; Count = new CountQueryOption(kvp.Value, context, _queryOptionParser); break; case "$expand": RawValues.Expand = kvp.Value; break; case "$format": RawValues.Format = kvp.Value; break; case "$skiptoken": RawValues.SkipToken = kvp.Value; break; default: // we don't throw if we can't recognize the query break; } } if (RawValues.Select != null || RawValues.Expand != null) { SelectExpand = new SelectExpandQueryOption(RawValues.Select, RawValues.Expand, context, _queryOptionParser); } Validator = new ODataQueryValidator(); }
/// <summary> /// Apply the individual query to the given IQueryable in the right order. /// </summary> /// <param name="query">The original <see cref="IQueryable"/>.</param> /// <param name="querySettings">The settings to use in query composition.</param> /// <returns>The new <see cref="IQueryable"/> after the query has been applied to.</returns> public virtual IQueryable ApplyTo(IQueryable query, ODataQuerySettings querySettings) { if (query == null) { throw Error.ArgumentNull("query"); } if (querySettings == null) { throw Error.ArgumentNull("querySettings"); } IQueryable result = query; // Construct the actual query and apply them in the following order: filter, orderby, skip, top if (Filter != null) { result = Filter.ApplyTo(result, querySettings, _assembliesResolver); } if (Count != null) { if (Request.ODataProperties().TotalCount == null) { long?count = Count.GetEntityCount(result); if (count.HasValue) { Request.ODataProperties().TotalCount = count.Value; } } if (ODataCountMediaTypeMapping.IsCountRequest(Request)) { return(result); } } OrderByQueryOption orderBy = OrderBy; // $skip or $top require a stable sort for predictable results. // Result limits require a stable sort to be able to generate a next page link. // If either is present in the query and we have permission, // generate an $orderby that will produce a stable sort. if (querySettings.EnsureStableOrdering && (Skip != null || Top != null || querySettings.PageSize.HasValue)) { // If there is no OrderBy present, we manufacture a default. // If an OrderBy is already present, we add any missing // properties necessary to make a stable sort. // Instead of failing early here if we cannot generate the OrderBy, // let the IQueryable backend fail (if it has to). orderBy = orderBy == null ? GenerateDefaultOrderBy(Context) : EnsureStableSortOrderBy(orderBy, Context); } if (orderBy != null) { result = orderBy.ApplyTo(result, querySettings); } if (Skip != null) { result = Skip.ApplyTo(result, querySettings); } if (Top != null) { result = Top.ApplyTo(result, querySettings); } if (SelectExpand != null) { SelectExpandClause processedClause = SelectExpand.ProcessLevels(); SelectExpandQueryOption newSelectExpand = new SelectExpandQueryOption( SelectExpand.RawSelect, SelectExpand.RawExpand, SelectExpand.Context, processedClause); Request.ODataProperties().SelectExpandClause = processedClause; result = newSelectExpand.ApplyTo(result, querySettings); } if (querySettings.PageSize.HasValue) { bool resultsLimited; result = LimitResults(result, querySettings.PageSize.Value, out resultsLimited); if (resultsLimited && Request.RequestUri != null && Request.RequestUri.IsAbsoluteUri && Request.ODataProperties().NextLink == null) { Uri nextPageLink = GetNextPageLink(Request, querySettings.PageSize.Value); Request.ODataProperties().NextLink = nextPageLink; } } return(result); }
public void ProcessLevelsCorrectly_WithMaxNestedLevels() { // Arrange var model = ODataLevelsTest.GetEdmModel(); var context = new ODataQueryContext( model, model.FindDeclaredType("System.Web.OData.Routing.LevelsEntity")); var selectExpand = new SelectExpandQueryOption( select: null, expand: "Parent($expand=DerivedAncestors($levels=max);$levels=2)", context: context); // Act SelectExpandClause clause = selectExpand.ProcessLevels(); // Assert Assert.True(clause.AllSelected); Assert.Equal(1, clause.SelectedItems.Count()); // Level 1 of Parent. var parent = Assert.IsType<ExpandedNavigationSelectItem>(clause.SelectedItems.Single()); Assert.Equal( "Parent", ((NavigationPropertySegment)parent.PathToNavigationProperty.FirstSegment).NavigationProperty.Name); Assert.Null(parent.LevelsOption); var clauseOfParent = parent.SelectAndExpand; Assert.True(clauseOfParent.AllSelected); Assert.Equal(2, clauseOfParent.SelectedItems.Count()); // Level 1 of DerivedAncestors. var derivedAncestors = Assert.Single( clauseOfParent.SelectedItems.OfType<ExpandedNavigationSelectItem>().Where( item => item.PathToNavigationProperty.FirstSegment is NavigationPropertySegment && ((NavigationPropertySegment)item.PathToNavigationProperty.FirstSegment).NavigationProperty.Name == "DerivedAncestors") ); Assert.Null(derivedAncestors.LevelsOption); var clauseOfDerivedAncestors = derivedAncestors.SelectAndExpand; Assert.True(clauseOfDerivedAncestors.AllSelected); Assert.Equal(0, clauseOfDerivedAncestors.SelectedItems.Count()); // Level 2 of Parent. parent = Assert.Single( clauseOfParent.SelectedItems.OfType<ExpandedNavigationSelectItem>().Where( item => item.PathToNavigationProperty.FirstSegment is NavigationPropertySegment && ((NavigationPropertySegment)item.PathToNavigationProperty.FirstSegment).NavigationProperty.Name == "Parent") ); Assert.Null(parent.LevelsOption); clauseOfParent = parent.SelectAndExpand; Assert.True(clauseOfParent.AllSelected); Assert.Equal(0, clauseOfParent.SelectedItems.Count()); }
public void ProcessLevelsCorrectly_WithMultipleProperties() { // Arrange var model = ODataLevelsTest.GetEdmModel(); var context = new ODataQueryContext( model, model.FindDeclaredType("System.Web.OData.Routing.LevelsEntity")); var selectExpand = new SelectExpandQueryOption( select: null, expand: "Parent($expand=Parent($levels=max),DerivedAncestors($levels=2;$select=ID)),BaseEntities($levels=2)", context: context); selectExpand.LevelsMaxLiteralExpansionDepth = 3; // Act SelectExpandClause clause = selectExpand.ProcessLevels(); // Assert Assert.True(clause.AllSelected); Assert.Equal(2, clause.SelectedItems.Count()); // Top level Parent. var parent = Assert.Single(clause.SelectedItems.OfType<ExpandedNavigationSelectItem>().Where( item => item.PathToNavigationProperty.FirstSegment is NavigationPropertySegment && ((NavigationPropertySegment)item.PathToNavigationProperty.FirstSegment).NavigationProperty.Name == "Parent")); Assert.Null(parent.LevelsOption); var clauseOfParent = parent.SelectAndExpand; Assert.True(clauseOfParent.AllSelected); Assert.Equal(2, clauseOfParent.SelectedItems.Count()); // Level 1 of inline Parent. var inlineParent = Assert.Single(clauseOfParent.SelectedItems.OfType<ExpandedNavigationSelectItem>().Where( item => item.PathToNavigationProperty.FirstSegment is NavigationPropertySegment && ((NavigationPropertySegment)item.PathToNavigationProperty.FirstSegment).NavigationProperty.Name == "Parent")); Assert.Null(inlineParent.LevelsOption); // Level 2 of inline Parent. var inlineParentClause = inlineParent.SelectAndExpand; Assert.True(inlineParentClause.AllSelected); Assert.Equal(1, inlineParentClause.SelectedItems.Count()); inlineParent = Assert.IsType<ExpandedNavigationSelectItem>(inlineParentClause.SelectedItems.Single()); Assert.Equal( "Parent", ((NavigationPropertySegment)inlineParent.PathToNavigationProperty.FirstSegment).NavigationProperty.Name); Assert.Null(inlineParent.LevelsOption); inlineParentClause = inlineParent.SelectAndExpand; Assert.True(inlineParentClause.AllSelected); Assert.Equal(0, inlineParentClause.SelectedItems.Count()); // Level 1 of inline DerivedAncestors. var inlineDerivedAncestors = Assert.Single(clauseOfParent.SelectedItems.OfType<ExpandedNavigationSelectItem>().Where( item => item.PathToNavigationProperty.FirstSegment is NavigationPropertySegment && ((NavigationPropertySegment)item.PathToNavigationProperty.FirstSegment).NavigationProperty.Name == "DerivedAncestors")); Assert.Null(inlineDerivedAncestors.LevelsOption); // Level 2 of inline DerivedAncestors. var inlineDerivedAncestorsClause = inlineDerivedAncestors.SelectAndExpand; Assert.False(inlineDerivedAncestorsClause.AllSelected); Assert.Equal(3, inlineDerivedAncestorsClause.SelectedItems.Count()); var idItem = Assert.Single(inlineDerivedAncestorsClause.SelectedItems.OfType<PathSelectItem>().Where( item => item.SelectedPath.FirstSegment is PropertySegment)); Assert.Equal("ID", ((PropertySegment)idItem.SelectedPath.FirstSegment).Property.Name); var derivedAncestorsItem = Assert.Single(inlineDerivedAncestorsClause.SelectedItems.OfType<PathSelectItem>().Where( item => item.SelectedPath.FirstSegment is NavigationPropertySegment)); Assert.Equal( "DerivedAncestors", ((NavigationPropertySegment)derivedAncestorsItem.SelectedPath.FirstSegment).NavigationProperty.Name); inlineDerivedAncestors = Assert.Single(inlineDerivedAncestorsClause.SelectedItems.OfType<ExpandedNavigationSelectItem>()); Assert.Equal( "DerivedAncestors", ((NavigationPropertySegment)inlineDerivedAncestors.PathToNavigationProperty.FirstSegment).NavigationProperty.Name); Assert.Null(inlineDerivedAncestors.LevelsOption); inlineDerivedAncestorsClause = inlineDerivedAncestors.SelectAndExpand; Assert.False(inlineDerivedAncestorsClause.AllSelected); Assert.Equal(1, inlineDerivedAncestorsClause.SelectedItems.Count()); idItem = Assert.Single(inlineDerivedAncestorsClause.SelectedItems.OfType<PathSelectItem>()); Assert.Equal("ID", ((PropertySegment)idItem.SelectedPath.FirstSegment).Property.Name); // Level 1 of BaseEntities. var baseEntities = Assert.Single(clause.SelectedItems.OfType<ExpandedNavigationSelectItem>().Where( item => item.PathToNavigationProperty.FirstSegment is NavigationPropertySegment && ((NavigationPropertySegment)item.PathToNavigationProperty.FirstSegment).NavigationProperty.Name == "BaseEntities")); Assert.Null(baseEntities.LevelsOption); // Level 2 of BaseEntities. var baseEntitiesClause = baseEntities.SelectAndExpand; Assert.True(baseEntitiesClause.AllSelected); Assert.Equal(1, baseEntitiesClause.SelectedItems.Count()); baseEntities = Assert.IsType<ExpandedNavigationSelectItem>(baseEntitiesClause.SelectedItems.Single()); Assert.Equal( "BaseEntities", ((NavigationPropertySegment)baseEntities.PathToNavigationProperty.FirstSegment).NavigationProperty.Name); Assert.Null(baseEntities.LevelsOption); baseEntitiesClause = baseEntities.SelectAndExpand; Assert.True(baseEntitiesClause.AllSelected); Assert.Equal(0, baseEntitiesClause.SelectedItems.Count()); }
public void ProcessLevelsCorrectly_NotAllSelected() { // Arrange var model = ODataLevelsTest.GetEdmModel(); var context = new ODataQueryContext( model, model.FindDeclaredType("System.Web.OData.Routing.LevelsEntity")); var selectExpand = new SelectExpandQueryOption( select: "Name", expand: "Parent($select=ID;$levels=max)", context: context); // Act SelectExpandClause clause = selectExpand.ProcessLevels(); // Assert // Level 1. Assert.False(clause.AllSelected); Assert.Equal(3, clause.SelectedItems.Count()); var nameSelectItem = Assert.Single(clause.SelectedItems.OfType<PathSelectItem>().Where( item => item.SelectedPath.FirstSegment is PropertySegment)); Assert.Equal("Name", ((PropertySegment)nameSelectItem.SelectedPath.FirstSegment).Property.Name); var parentSelectItem = Assert.Single(clause.SelectedItems.OfType<PathSelectItem>().Where( item => item.SelectedPath.FirstSegment is NavigationPropertySegment)); Assert.Equal( "Parent", ((NavigationPropertySegment)parentSelectItem.SelectedPath.FirstSegment).NavigationProperty.Name); var expandedItem = Assert.Single(clause.SelectedItems.OfType<ExpandedNavigationSelectItem>()); Assert.Equal( "Parent", ((NavigationPropertySegment)expandedItem.PathToNavigationProperty.FirstSegment).NavigationProperty.Name); Assert.Null(expandedItem.LevelsOption); // Level 2. clause = expandedItem.SelectAndExpand; Assert.False(clause.AllSelected); Assert.Equal(3, clause.SelectedItems.Count()); var idSelectItem = Assert.Single(clause.SelectedItems.OfType<PathSelectItem>().Where( item => item.SelectedPath.FirstSegment is PropertySegment)); Assert.Equal("ID", ((PropertySegment)idSelectItem.SelectedPath.FirstSegment).Property.Name); parentSelectItem = Assert.Single(clause.SelectedItems.OfType<PathSelectItem>().Where( item => item.SelectedPath.FirstSegment is NavigationPropertySegment)); Assert.Equal( "Parent", ((NavigationPropertySegment)parentSelectItem.SelectedPath.FirstSegment).NavigationProperty.Name); expandedItem = Assert.Single(clause.SelectedItems.OfType<ExpandedNavigationSelectItem>()); Assert.Equal( "Parent", ((NavigationPropertySegment)expandedItem.PathToNavigationProperty.FirstSegment).NavigationProperty.Name); Assert.Null(expandedItem.LevelsOption); clause = expandedItem.SelectAndExpand; Assert.False(clause.AllSelected); Assert.Equal(1, clause.SelectedItems.Count()); idSelectItem = Assert.IsType<PathSelectItem>(clause.SelectedItems.Single()); Assert.Equal("ID", ((PropertySegment)idSelectItem.SelectedPath.FirstSegment).Property.Name); }
public void SelectExpandClause_Property_ParsesRawSelectAndRawExpand() { // Arrange IEdmModel model = _model.Model; _model.Model.SetAnnotationValue<ClrTypeAnnotation>(_model.Customer, new ClrTypeAnnotation(typeof(Customer))); ODataQueryContext context = new ODataQueryContext(model, typeof(Customer)); SelectExpandQueryOption option = new SelectExpandQueryOption("ID,Name,SimpleEnum,Orders", "Orders", context); // Act SelectExpandClause selectExpandClause = option.SelectExpandClause; // Assert Assert.NotEmpty(selectExpandClause.SelectedItems.OfType<PathSelectItem>()); Assert.NotEmpty(selectExpandClause.SelectedItems.OfType<ExpandedNavigationSelectItem>()); }
public void SelectExpandClause_Property_ParsesWithEdmTypeAndNavigationSource() { // Arrange IEdmModel model = _model.Model; _model.Model.SetAnnotationValue(_model.Customer, new ClrTypeAnnotation(typeof(Customer))); ODataPath odataPath = new ODataPath(new EntitySetPathSegment(_model.Customers)); ODataQueryContext context = new ODataQueryContext(model, _model.Customer, odataPath); SelectExpandQueryOption option = new SelectExpandQueryOption("ID,Name,SimpleEnum,Orders", "Orders", context); // Act SelectExpandClause selectExpandClause = option.SelectExpandClause; // Assert Assert.NotEmpty(selectExpandClause.SelectedItems.OfType<PathSelectItem>()); Assert.NotEmpty(selectExpandClause.SelectedItems.OfType<ExpandedNavigationSelectItem>()); }