public void CanApplyOrderByThenBy() { var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetServiceModel(); var context = new ODataQueryContext(model, typeof(Customer)) { RequestContainer = new MockContainer() }; var orderByOption = new OrderByQueryOption("Name,Website", context); var customers = (new List <Customer> { new Customer { CustomerId = 1, Name = "ACME", Website = "http://www.acme.net" }, new Customer { CustomerId = 2, Name = "AAAA", Website = "http://www.aaaa.com" }, new Customer { CustomerId = 3, Name = "ACME", Website = "http://www.acme.com" } }).AsQueryable(); var results = orderByOption.ApplyTo(customers).ToArray(); Assert.Equal(2, results[0].CustomerId); Assert.Equal(3, results[1].CustomerId); Assert.Equal(1, results[2].CustomerId); }
public void CanApplyOrderByQueryCaseInsensitive(string orderbyValue) { var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetEdmModel(); var context = new ODataQueryContext(model, typeof(Customer)) { RequestContainer = new MockContainer() }; var orderby = new OrderByQueryOption(orderbyValue, context); var customers = (new List <Customer> { new Customer { CustomerId = 2, Name = "Aaron" }, new Customer { CustomerId = 1, Name = "Andy" }, new Customer { CustomerId = 3, Name = "Alex" } }).AsQueryable(); var results = orderby.ApplyTo(customers).ToArray(); Assert.Equal(1, results[0].CustomerId); Assert.Equal(2, results[1].CustomerId); Assert.Equal(3, results[2].CustomerId); }
public void CanApplyOrderByDescending() { var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetServiceModel(); var context = new ODataQueryContext(model, typeof(Customer)) { RequestContainer = new MockContainer() }; var orderByOption = new OrderByQueryOption("Name desc", context); var customers = (new List <Customer> { new Customer { CustomerId = 1, Name = "Andy" }, new Customer { CustomerId = 2, Name = "Aaron" }, new Customer { CustomerId = 3, Name = "Alex" } }).AsQueryable(); var results = orderByOption.ApplyTo(customers).ToArray(); Assert.Equal(1, results[0].CustomerId); Assert.Equal(3, results[1].CustomerId); Assert.Equal(2, results[2].CustomerId); }
public void ApplyTo_NestedProperties_DoesNotHandleNullPropagation_IfExplicitInSettings() { // Arrange var model = new ODataModelBuilder().Add_Customer_EntityType_With_Address().Add_Customers_EntitySet().GetServiceModel(); var context = new ODataQueryContext(model, typeof(Customer)) { RequestContainer = new MockContainer() }; var orderByOption = new OrderByQueryOption("Address/City asc", context); var customers = (new List <Customer> { new Customer { CustomerId = 1, Address = null }, new Customer { CustomerId = 2, Address = new Address { City = "B" } }, new Customer { CustomerId = 3, Address = new Address { City = "A" } } }).AsQueryable(); ODataQuerySettings settings = new ODataQuerySettings { HandleNullPropagation = HandleNullPropagationOption.False }; // Act & Assert ExceptionAssert.Throws <NullReferenceException>(() => orderByOption.ApplyTo(customers, settings).ToArray()); }
public void ApplyTo_NestedProperties_HandlesNullPropagation_Succeeds() { // Arrange var model = new ODataModelBuilder().Add_Customer_EntityType_With_Address().Add_Customers_EntitySet().GetServiceModel(); var context = new ODataQueryContext(model, typeof(Customer)) { RequestContainer = new MockContainer() }; var orderByOption = new OrderByQueryOption("Address/City asc", context); var customers = (new List <Customer> { new Customer { CustomerId = 1, Address = null }, new Customer { CustomerId = 2, Address = new Address { City = "B" } }, new Customer { CustomerId = 3, Address = new Address { City = "A" } } }).AsQueryable(); // Act var results = orderByOption.ApplyTo(customers).ToArray(); // Assert Assert.Equal(1, results[0].CustomerId); Assert.Equal(3, results[1].CustomerId); Assert.Equal(2, results[2].CustomerId); }
public void ApplyTo_PropertyAliased_IfEnabled(bool modelAliasing, string propertyName) { // Arrange var builder = ODataConventionModelBuilderHelper.CreateWithModelAliasing(modelAliasing); builder.EntitySet <PropertyAlias>("PropertyAliases"); var model = builder.GetEdmModel(); var context = new ODataQueryContext(model, typeof(PropertyAlias)) { RequestContainer = new MockContainer(model) }; var orderByOption = new OrderByQueryOption(propertyName, context); IEnumerable <PropertyAlias> propertyAliases = FilterQueryOptionTest.PropertyAliasTestData; // Act IQueryable queryable = orderByOption.ApplyTo(propertyAliases.AsQueryable()); // Assert Assert.NotNull(queryable); IEnumerable <PropertyAlias> actualCustomers = Assert.IsAssignableFrom <IEnumerable <PropertyAlias> >(queryable); Assert.Equal( new[] { "abc", "def", "xyz" }, actualCustomers.Select(propertyAlias => propertyAlias.FirstName)); }
public void ApplyToEnums_ReturnsCorrectQueryable() { // Arrange var builder = ODataConventionModelBuilderFactory.Create(); builder.EntitySet <EnumModel>("EnumModels"); var model = builder.GetEdmModel(); var context = new ODataQueryContext(model, typeof(EnumModel)) { RequestContainer = new MockContainer() }; var orderbyOption = new OrderByQueryOption("Flag", context); IEnumerable <EnumModel> enumModels = FilterQueryOptionTest.EnumModelTestData; // Act IQueryable queryable = orderbyOption.ApplyTo(enumModels.AsQueryable()); // Assert Assert.NotNull(queryable); IEnumerable <EnumModel> actualCustomers = Assert.IsAssignableFrom <IEnumerable <EnumModel> >(queryable); Assert.Equal( new int[] { 5, 2, 1, 3, 6 }, actualCustomers.Select(enumModel => enumModel.Id)); }
public void CanApplySkipOrderby() { var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetEdmModel(); var context = new ODataQueryContext(model, typeof(Customer)) { RequestContainer = new MockServiceProvider() }; var orderbyOption = new OrderByQueryOption("Name", context); var skipOption = new SkipQueryOption("1", context); var customers = (new List <Customer> { new Customer { Id = 1, Name = "Andy" }, new Customer { Id = 2, Name = "Aaron" }, new Customer { Id = 3, Name = "Alex" } }).AsQueryable(); IQueryable queryable = orderbyOption.ApplyTo(customers); queryable = skipOption.ApplyTo(queryable, new ODataQuerySettings()); var results = ((IQueryable <Customer>)queryable).ToArray(); Assert.Equal(2, results.Length); Assert.Equal(3, results[0].Id); Assert.Equal(1, results[1].Id); }
public void CanApplyOrderBy_WithParameterAlias() { // Arrange var model = new ODataModelBuilder().Add_Customer_EntityType_With_Address().Add_Address_ComplexType().GetServiceModel(); var parser = new ODataQueryOptionParser( model, model.FindType("Microsoft.AspNet.OData.Test.Builder.TestModels.Customer"), model.FindDeclaredNavigationSource("Default.Container.Customers"), new Dictionary <string, string> { { "$orderby", "@q desc,@p asc" }, { "@q", "Address/HouseNumber" }, { "@p", "CustomerId" } }); var context = new ODataQueryContext(model, typeof(Customer)) { RequestContainer = new MockContainer() }; var orderByOption = new OrderByQueryOption("@q desc,@p asc", context, parser); var customers = (new List <Customer> { new Customer { CustomerId = 1, Address = new Address { HouseNumber = 2 } }, new Customer { CustomerId = 2, Address = new Address { HouseNumber = 1 } }, new Customer { CustomerId = 3, Address = new Address { HouseNumber = 3 } }, new Customer { CustomerId = 4, Address = new Address { HouseNumber = 2 } }, new Customer { CustomerId = 5, Address = new Address { HouseNumber = 1 } }, }).AsQueryable(); // Act var results = orderByOption.ApplyTo(customers).ToArray(); // Assert Assert.Equal(3, results[0].CustomerId); Assert.Equal(1, results[1].CustomerId); Assert.Equal(4, results[2].CustomerId); Assert.Equal(2, results[3].CustomerId); Assert.Equal(5, results[4].CustomerId); }
public void ApplyInValidOrderbyQueryThrows(string orderbyValue) { var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetEdmModel(); var context = new ODataQueryContext(model, typeof(Customer), "Customers"); var orderby = new OrderByQueryOption(orderbyValue, context); Assert.Throws<ODataException>(() => orderby.ApplyTo(ODataQueryOptionTest.Customers)); }
public void OrderByDuplicateItThrows() { // Arrange var context = new ODataQueryContext(EdmCoreModel.Instance, typeof(int)); var orderbyOption = new OrderByQueryOption("$it, $it", context); // Act ExceptionAssert.Throws <ODataException>( () => orderbyOption.ApplyTo(Enumerable.Empty <int>().AsQueryable()), "Multiple '$it' nodes are not supported in '$orderby'."); }
public void ApplyInValidOrderbyQueryThrows(string orderbyValue) { var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetEdmModel(); var context = new ODataQueryContext(model, typeof(Customer)) { RequestContainer = new MockContainer() }; var orderby = new OrderByQueryOption(orderbyValue, context); ExceptionAssert.Throws <ODataException>(() => orderby.ApplyTo(ODataQueryOptionTest.Customers)); }
public void ApplyTo_WithUnTypedContext_Throws_InvalidOperation() { // Arrange CustomersModelWithInheritance model = new CustomersModelWithInheritance(); ODataQueryContext context = new ODataQueryContext(model.Model, model.Customer); OrderByQueryOption orderBy = new OrderByQueryOption("ID desc", context); IQueryable queryable = new Mock <IQueryable>().Object; // Act & Assert ExceptionAssert.Throws <NotSupportedException>(() => orderBy.ApplyTo(queryable), "The query option is not bound to any CLR type. 'ApplyTo' is only supported with a query option bound to a CLR type."); }
public static Expression ToExpression <TPublicEntity>(this OrderByQueryOption filter) where TPublicEntity : BaseDto { if (filter == null) { throw new ArgumentNullException(nameof(filter)); } IQueryable queryable = Enumerable.Empty <TPublicEntity>().AsQueryable(); queryable = filter.ApplyTo(queryable, new ODataQuerySettings()); return(queryable.Expression); }
public void CanOrderByChildPropertyAscending() { // Arrange var query = new List <Product> { new Product { Category = new Category { Description = "b" } }, new Product { Category = new Category { Description = "a" } }, new Product { Category = new Category { Description = "d" } }, new Product { Category = new Category { Description = "c" } } } .AsQueryable(); var sortPropertyPath = string.Concat( nameof(Product.Category), ".", nameof(Category.Description)); var orderByNodes = new List <OrderByNode> { new OrderByNode(sortPropertyPath) }; var options = new OrderByQueryOption(orderByNodes); // Act var results = options.ApplyTo(query).ToList(); // Assert Assert.Collection( results, o => Assert.Equal("a", o.Category.Description), o => Assert.Equal("b", o.Category.Description), o => Assert.Equal("c", o.Category.Description), o => Assert.Equal("d", o.Category.Description)); }
public void ApplyTo_NestedProperties_DoesNotHandleNullPropagation_IfExplicitInSettings() { // Arrange var model = new ODataModelBuilder().Add_Customer_EntityType_With_Address().Add_Customers_EntitySet().GetServiceModel(); var orderByOption = new OrderByQueryOption("Address/City asc", new ODataQueryContext(model, typeof(Customer)), null); var customers = (new List<Customer>{ new Customer { CustomerId = 1, Address = null }, new Customer { CustomerId = 2, Address = new Address { City = "B" } }, new Customer { CustomerId = 3, Address = new Address { City = "A" } } }).AsQueryable(); ODataQuerySettings settings = new ODataQuerySettings { HandleNullPropagation = HandleNullPropagationOption.False }; // Act & Assert Assert.Throws<NullReferenceException>(() => orderByOption.ApplyTo(customers, settings).ToArray()); }
public void OrderByDuplicatePropertyOfComplexTypeThrows() { // Arrange var model = new ODataModelBuilder().Add_Customer_EntityType_With_Address().Add_Customers_EntitySet().GetServiceModel(); var context = new ODataQueryContext(model, typeof(Customer)) { RequestContainer = new MockContainer() }; var orderbyOption = new OrderByQueryOption("Address/City, Address/City", context); // Act ExceptionAssert.Throws <ODataException>( () => orderbyOption.ApplyTo(Enumerable.Empty <Customer>().AsQueryable()), "Duplicate property named 'Address/City' is not supported in '$orderby'."); }
public static Expression <Func <TElement, bool> > ToExpression <TElement>(this OrderByQueryOption orderBy) { var param = Expression.Parameter(typeof(TElement)); IQueryable queryable = Enumerable.Empty <TElement>().AsQueryable(); if (orderBy != null) { queryable = orderBy.ApplyTo(queryable, new ODataQuerySettings()); var mce = queryable.Expression as MethodCallExpression; if (mce != null) { var quote = mce.Arguments[1] as UnaryExpression; if (quote != null) { return(quote.Operand as Expression <Func <TElement, bool> >); } } } return(Expression.Lambda <Func <TElement, bool> >(Expression.Constant(true), param)); }
public void CanApplySkipOrderby() { var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetServiceModel(); var context = new ODataQueryContext(model, typeof(Customer)); var orderbyOption = new OrderByQueryOption("Name", context, queryTranslator: null); var skipOption = new SkipQueryOption("1", context); var customers = (new List<Customer>{ new Customer { CustomerId = 1, Name = "Andy" }, new Customer { CustomerId = 2, Name = "Aaron" }, new Customer { CustomerId = 3, Name = "Alex" } }).AsQueryable(); IQueryable queryable = orderbyOption.ApplyTo(customers); queryable = skipOption.ApplyTo(queryable, new ODataQuerySettings()); var results = ((IQueryable<Customer>)queryable).ToArray(); Assert.Equal(2, results.Length); Assert.Equal(3, results[0].CustomerId); Assert.Equal(1, results[1].CustomerId); }
public void ApplyToEnums_ReturnsCorrectQueryable() { // Arrange var builder = new ODataConventionModelBuilder(); builder.EntitySet<EnumModel>("EnumModels"); var model = builder.GetEdmModel(); var context = new ODataQueryContext(model, typeof(EnumModel)); var orderbyOption = new OrderByQueryOption("Flag", context, null); IEnumerable<EnumModel> enumModels = FilterQueryOptionTest.EnumModelTestData; // Act IQueryable queryable = orderbyOption.ApplyTo(enumModels.AsQueryable()); // Assert Assert.NotNull(queryable); IEnumerable<EnumModel> actualCustomers = Assert.IsAssignableFrom<IEnumerable<EnumModel>>(queryable); Assert.Equal( new int[] { 2, 1, 3 }, actualCustomers.Select(enumModel => enumModel.Id)); }
public void CanApplyOrderBy_WithNestedParameterAlias() { // Arrange var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetServiceModel(); var parser = new ODataQueryOptionParser( model, model.FindType("Microsoft.AspNet.OData.Test.Builder.TestModels.Customer"), model.FindDeclaredNavigationSource("Default.Container.Customers"), new Dictionary <string, string> { { "$orderby", "@p1" }, { "@p2", "Name" }, { "@p1", "@p2" } }); var context = new ODataQueryContext(model, typeof(Customer)) { RequestContainer = new MockContainer() }; var orderByOption = new OrderByQueryOption("@p1", context, parser); var customers = (new List <Customer> { new Customer { CustomerId = 1, Name = "Andy" }, new Customer { CustomerId = 2, Name = "Aaron" }, new Customer { CustomerId = 3, Name = "Alex" } }).AsQueryable(); // Act var results = orderByOption.ApplyTo(customers).ToArray(); // Assert Assert.Equal(2, results[0].CustomerId); Assert.Equal(3, results[1].CustomerId); Assert.Equal(1, results[2].CustomerId); }
public void CanOrderByMultipleProperties() { // Arrange var query = new List <Product> { new Product { Id = 2, Price = 1.23m }, new Product { Id = 4, Price = 5.23m }, new Product { Id = 1, Price = 1.23m }, new Product { Id = 3, Price = 0.23m } } .AsQueryable(); var orderByNodes = new List <OrderByNode> { new OrderByNode(nameof(Product.Price), OrderByDirection.Descending), new OrderByNode(nameof(Product.Id)) }; var options = new OrderByQueryOption(orderByNodes); // Act var results = options.ApplyTo(query).ToList(); // Assert Assert.Collection( results, o => Assert.Equal(4, o.Id), o => Assert.Equal(1, o.Id), o => Assert.Equal(2, o.Id), o => Assert.Equal(3, o.Id)); }
public void CanOrderByDescending() { // Arrange var query = new List <Product> { new Product { Id = 2 }, new Product { Id = 1 }, new Product { Id = 4 }, new Product { Id = 3 } } .AsQueryable(); var orderByNodes = new List <OrderByNode> { new OrderByNode(nameof(Product.Id), OrderByDirection.Descending) }; var options = new OrderByQueryOption(orderByNodes); // Act var results = options.ApplyTo(query).ToList(); // Assert Assert.Collection( results, o => Assert.Equal(4, o.Id), o => Assert.Equal(3, o.Id), o => Assert.Equal(2, o.Id), o => Assert.Equal(1, o.Id)); }
public void OrderByIsCaseInsensitive() { // Arrange var query = new List <Product> { new Product { Id = 2 }, new Product { Id = 1 }, new Product { Id = 4 }, new Product { Id = 3 } } .AsQueryable(); var orderByNodes = new List <OrderByNode> { new OrderByNode("iD") }; var options = new OrderByQueryOption(orderByNodes); // Act var results = options.ApplyTo(query).ToList(); // Assert Assert.Collection( results, o => Assert.Equal(1, o.Id), o => Assert.Equal(2, o.Id), o => Assert.Equal(3, o.Id), o => Assert.Equal(4, o.Id)); }
public void OrderByDuplicatePropertyThrows() { // Arrange var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetServiceModel(); var context = new ODataQueryContext(model, typeof(Customer)); var orderbyOption = new OrderByQueryOption("Name, Name", context); // Act Assert.Throws<ODataException>( () => orderbyOption.ApplyTo(Enumerable.Empty<Customer>().AsQueryable()), "Duplicate property named 'Name' is not supported in '$orderby'."); }
public void CanApplyOrderByDescThenByDesc() { var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetServiceModel(); var orderByOption = new OrderByQueryOption("Name desc,Website desc", new ODataQueryContext(model, typeof(Customer))); var customers = (new List<Customer>{ new Customer { CustomerId = 1, Name = "ACME", Website = "http://www.acme.net" }, new Customer { CustomerId = 2, Name = "AAAA", Website = "http://www.aaaa.com" }, new Customer { CustomerId = 3, Name = "ACME", Website = "http://www.acme.com" } }).AsQueryable(); var results = orderByOption.ApplyTo(customers).ToArray(); Assert.Equal(1, results[0].CustomerId); Assert.Equal(3, results[1].CustomerId); Assert.Equal(2, results[2].CustomerId); }
public async Task <IActionResult> OData(ODataQueryOptions <DeveloperDto> oDataQuery) { var edmModel = EdmModelConfig.GetEdmModel(); var edmEntitySet = edmModel.FindDeclaredEntitySet(nameof(Developer)); var context = new ODataQueryContext(edmModel, typeof(Developer), oDataQuery.Context.Path); var edmType = context.ElementType; var parameters = new Dictionary <string, string>(); if (!string.IsNullOrWhiteSpace(oDataQuery.RawValues.Filter)) { parameters.Add("$filter", oDataQuery.RawValues.Filter); } if (!string.IsNullOrWhiteSpace(oDataQuery.RawValues.Expand)) { parameters.Add("$expand", oDataQuery.RawValues.Expand); } if (!string.IsNullOrWhiteSpace(oDataQuery.RawValues.OrderBy)) { parameters.Add("$orderby", oDataQuery.RawValues.OrderBy); } var parser = new ODataQueryOptionParser(edmModel, edmType, edmEntitySet, parameters); var queryable = (IQueryable <Developer>)_databaseContext.Developer; if (!string.IsNullOrWhiteSpace(oDataQuery.RawValues.Filter)) { var filter = new FilterQueryOption(oDataQuery.RawValues.Filter, context, parser); queryable = (IQueryable <Developer>)filter.ApplyTo(queryable, new ODataQuerySettings()); } if (!string.IsNullOrWhiteSpace(oDataQuery.RawValues.OrderBy)) { var orderBy = new OrderByQueryOption(oDataQuery.RawValues.OrderBy, context, parser); queryable = orderBy.ApplyTo(queryable, new ODataQuerySettings()); } IQueryable <object> expandableQueryable = null; if (!string.IsNullOrWhiteSpace(oDataQuery.RawValues.Expand)) { var expand = new SelectExpandQueryOption(null, oDataQuery.RawValues.Expand, context, parser); expandableQueryable = (IQueryable <object>)expand.ApplyTo(queryable, new ODataQuerySettings()); } int pageIndex = 1; var hasPageIndex = oDataQuery.Request.Query.TryGetValue("$pageindex", out StringValues pageIndexRaw); if (hasPageIndex) { var isTrue = int.TryParse(pageIndexRaw, out int _pageIndexRaw); pageIndex = (isTrue && _pageIndexRaw > 0) ? _pageIndexRaw : pageIndex; } int pageSize = 10; var hasPageSize = oDataQuery.Request.Query.TryGetValue("$pagesize", out StringValues pageSizeRaw); if (hasPageSize) { var isTrue = int.TryParse(pageSizeRaw, out int _pageSizeRaw); pageSize = (isTrue && _pageSizeRaw > 0) ? _pageSizeRaw : pageSize; } IQueryable <object> queryToExecute = expandableQueryable ?? queryable; var records = await queryToExecute.Skip((pageIndex - 1) *pageSize).Take(pageSize).ToListAsync(); var count = await queryToExecute.CountAsync(); var pageList = new PageList <Developer>(MapDomain(records).ToList(), count, pageIndex, pageSize); var response = PageListDto <DeveloperDto> .Map(pageList, DeveloperDto.MapDomainToDto); return(Ok(response)); }
public void ApplyTo_PropertyAliased_IfEnabled(bool modelAliasing, string propertyName) { // Arrange var builder = new ODataConventionModelBuilder { ModelAliasingEnabled = modelAliasing }; builder.EntitySet<PropertyAlias>("PropertyAliases"); var model = builder.GetEdmModel(); var context = new ODataQueryContext(model, typeof(PropertyAlias)); var orderByOption = new OrderByQueryOption(propertyName, context); IEnumerable<PropertyAlias> propertyAliases = FilterQueryOptionTest.PropertyAliasTestData; // Act IQueryable queryable = orderByOption.ApplyTo(propertyAliases.AsQueryable()); // Assert Assert.NotNull(queryable); IEnumerable<PropertyAlias> actualCustomers = Assert.IsAssignableFrom<IEnumerable<PropertyAlias>>(queryable); Assert.Equal( new[] { "abc", "def", "xyz" }, actualCustomers.Select(propertyAlias => propertyAlias.FirstName)); }
public override IQueryable ApplyTo(IQueryable query, ODataQuerySettings querySettings) { if (query == null) { throw new ArgumentNullException(nameof(query)); } if (querySettings == null) { throw new ArgumentNullException(nameof(querySettings)); } var 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 (InlineCount != null && Request.ODataProperties().TotalCount == null) { long?count = InlineCount.GetEntityCount(result); if (count.HasValue) { Request.ODataProperties().TotalCount = count.Value; } } 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 (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 ApplyTo_NestedProperties_WithDuplicatePathType_Succeeds() { // Arrange var model = new ODataModelBuilder().Add_Customer_EntityType_With_DuplicatedAddress() .Add_Customers_EntitySet() .GetEdmModel(); var context = new ODataQueryContext(model, typeof(Customer)) { RequestContainer = new MockServiceProvider() }; var orderByOption = new OrderByQueryOption("City,Address/City,WorkAddress/City", context); var customers = (new List <Customer> { new Customer { Id = 1, City = "B", Address = new Address { City = "B" }, WorkAddress = new Address { City = "B" } }, new Customer { Id = 2, City = "B", Address = new Address { City = "B" }, WorkAddress = new Address { City = "A" } }, new Customer { Id = 3, City = "B", Address = new Address { City = "A" }, WorkAddress = new Address { City = "A" } }, new Customer { Id = 4, City = "A", Address = new Address { City = "A" }, WorkAddress = new Address { City = "A" } } }).AsQueryable(); // Act var results = orderByOption.ApplyTo(customers).ToArray(); // Assert Assert.Equal(4, results[0].Id); Assert.Equal(3, results[1].Id); Assert.Equal(2, results[2].Id); Assert.Equal(1, results[3].Id); }
public void CanApplyOrderBy_WithCollectionCount(string orderby) { // Arrange var model = new ODataModelBuilder() .Add_Order_EntityType() .Add_Customer_EntityType_With_Address() .Add_CustomerOrders_Relationship() .Add_Customer_EntityType_With_CollectionProperties() .Add_Customers_EntitySet() .GetEdmModel(); var parser = new ODataQueryOptionParser( model, model.FindType("Microsoft.AspNetCore.OData.Tests.Models.Customer"), model.FindDeclaredNavigationSource("Default.Container.Customers"), new Dictionary <string, string> { { "$orderby", orderby } }); var orderByOption = new OrderByQueryOption(orderby, new ODataQueryContext(model, typeof(Customer)), parser); var customers = (new List <Customer> { new Customer { Id = 1, Name = "Andy", Orders = new List <Order> { new Order { OrderId = 1 }, new Order { OrderId = 2 } }, Addresses = new List <Address> { new Address { City = "1" }, new Address { City = "2" } }, Aliases = new List <string> { "1", "2" } }, new Customer { Id = 2, Name = "Aaron", Orders = new List <Order> { new Order { OrderId = 3 } }, Addresses = new List <Address> { new Address { City = "3" } }, Aliases = new List <string> { "3" } }, new Customer { Id = 3, Name = "Alex" } }).AsQueryable(); // Act var results = orderByOption.ApplyTo(customers).ToArray(); // Assert Assert.Equal(3, results[0].Id); Assert.Equal(2, results[1].Id); Assert.Equal(1, results[2].Id); }
public void ApplyTo_WithUnTypedContext_Throws_InvalidOperation() { // Arrange CustomersModelWithInheritance model = new CustomersModelWithInheritance(); ODataQueryContext context = new ODataQueryContext(model.Model, model.Customer); OrderByQueryOption orderBy = new OrderByQueryOption("ID desc", context); IQueryable queryable = new Mock<IQueryable>().Object; // Act & Assert Assert.Throws<NotSupportedException>(() => orderBy.ApplyTo(queryable), "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 OrderByDuplicateItThrows() { // Arrange var context = new ODataQueryContext(EdmCoreModel.Instance, typeof(int)); var orderbyOption = new OrderByQueryOption("$it, $it", context); // Act Assert.Throws<ODataException>( () => orderbyOption.ApplyTo(Enumerable.Empty<int>().AsQueryable()), "Multiple '$it' nodes are not supported in '$orderby'."); }
public static Func <IQueryable <Creative>, IOrderedQueryable <Creative> > ToExpression <TElement>(this OrderByQueryOption orderBy) { if (orderBy == null) { return(null); } IQueryable queryable = Enumerable.Empty <TElement>().AsQueryable(); var param = Expression.Parameter(typeof(Creative)); //queryable = orderBy.ApplyTo(queryable, new ODataQuerySettings()); IOrderedQueryable <Creative> orderQueryable = (IOrderedQueryable <Creative>)orderBy.ApplyTo(queryable, new ODataQuerySettings()); Func <IQueryable <Creative>, IOrderedQueryable <Creative> > orderingFunc = query => orderQueryable; return(orderingFunc); }
// GET: odata/MyEntities //[EnableQuery] //public IQueryable<MyEntity> GetMyEntities(ODataQueryOptions opts) //{ // IQueryable results = opts.ApplyTo(db.MyEntities.AsQueryable()); // return results as IQueryable<MyEntity>; //} // GET: odata/MyEntities //[EnableQuery] public IQueryable <MyEntity> GetMyEntities(ODataQueryOptions opts) { var settings = new ODataValidationSettings() { // Initialize settings as needed. AllowedFunctions = AllowedFunctions.AllMathFunctions }; opts.Validate(settings); //IQueryable results = db.MyEntities.AsQueryable<MyEntity>(); //if (opts.Filter != null) //{ // results = opts.Filter.ApplyTo(results, new ODataQuerySettings() { EnableConstantParameterization = false, EnsureStableOrdering = false }); //} //results = results.Decompile(); //results.Decompile //IQueryable results = MyApplyToWithDecompile(db.MyEntities.AsQueryable(), opts); //return results as IQueryable<MyEntity>; //return db.MyEntities; IQueryable result = db.MyEntities.AsQueryable(); ODataQuerySettings querySettings = new ODataQuerySettings() { EnableConstantParameterization = false, EnsureStableOrdering = false }; // Construct the actual query and apply them in the following order: filter, orderby, skip, top if (opts.Filter != null) { result = opts.Filter.ApplyTo(result, querySettings); result = ((result as IQueryable <MyEntity>).Decompile()).AsQueryable(); } if (opts.InlineCount != null && Request.ODataProperties().TotalCount == null) { long?count = opts.InlineCount.GetEntityCount(result); if (count.HasValue) { Request.ODataProperties().TotalCount = count.Value; } } OrderByQueryOption orderBy = opts.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 && (opts.Skip != null || opts.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(opts.Context) : EnsureStableSortOrderBy(orderBy, opts.Context); } if (orderBy != null) { result = orderBy.ApplyTo(result, querySettings); } if (opts.Skip != null) { result = opts.Skip.ApplyTo(result, querySettings); } if (opts.Top != null) { result = opts.Top.ApplyTo(result, querySettings); } if (opts.SelectExpand != null) { Request.ODataProperties().SelectExpandClause = opts.SelectExpand.SelectExpandClause; result = opts.SelectExpand.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 as IQueryable <MyEntity>); // this compiles and works in most cases except when using $top with anything else. Even if no results are found. //return result.AsQueryable(); // this doesn't compile, Error: Cannot implicitly convert type 'System.Linq.IQueryable' to 'System.Linq.IQueryable<MyEntity>. An explicit conversion exists (are you missing a cast?) }
public void ApplyTo_NestedProperties_HandlesNullPropagation_Succeeds() { // Arrange var model = new ODataModelBuilder().Add_Customer_EntityType_With_Address().Add_Customers_EntitySet().GetServiceModel(); var orderByOption = new OrderByQueryOption("Address/City asc", new ODataQueryContext(model, typeof(Customer))); var customers = (new List<Customer>{ new Customer { CustomerId = 1, Address = null }, new Customer { CustomerId = 2, Address = new Address { City = "B" } }, new Customer { CustomerId = 3, Address = new Address { City = "A" } } }).AsQueryable(); // Act var results = orderByOption.ApplyTo(customers).ToArray(); // Assert Assert.Equal(1, results[0].CustomerId); Assert.Equal(3, results[1].CustomerId); Assert.Equal(2, results[2].CustomerId); }
public void CanApplyOrderBy_WithParameterAlias() { // Arrange var model = new ODataModelBuilder().Add_Customer_EntityType_With_Address().Add_Address_ComplexType().GetServiceModel(); var parser = new ODataQueryOptionParser( model, model.FindType("System.Web.OData.Builder.TestModels.Customer"), model.FindDeclaredNavigationSource("Default.Container.Customers"), new Dictionary<string, string> { { "$orderby", "@q desc,@p asc" }, { "@q", "Address/HouseNumber" }, { "@p", "CustomerId" } }); var orderByOption = new OrderByQueryOption("@q desc,@p asc", new ODataQueryContext(model, typeof(Customer)), parser); var customers = (new List<Customer>{ new Customer { CustomerId = 1, Address = new Address{HouseNumber = 2}}, new Customer { CustomerId = 2, Address = new Address{HouseNumber = 1}}, new Customer { CustomerId = 3, Address = new Address{HouseNumber = 3}}, new Customer { CustomerId = 4, Address = new Address{HouseNumber = 2}}, new Customer { CustomerId = 5, Address = new Address{HouseNumber = 1}}, }).AsQueryable(); // Act var results = orderByOption.ApplyTo(customers).ToArray(); // Assert Assert.Equal(3, results[0].CustomerId); Assert.Equal(1, results[1].CustomerId); Assert.Equal(4, results[2].CustomerId); Assert.Equal(2, results[3].CustomerId); Assert.Equal(5, results[4].CustomerId); }
public void CanApplyOrderBy() { var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetServiceModel(); var orderByOption = new OrderByQueryOption("Name", new ODataQueryContext(model, typeof(Customer))); var customers = (new List<Customer>{ new Customer { CustomerId = 1, Name = "Andy" }, new Customer { CustomerId = 2, Name = "Aaron" }, new Customer { CustomerId = 3, Name = "Alex" } }).AsQueryable(); var results = orderByOption.ApplyTo(customers).ToArray(); Assert.Equal(2, results[0].CustomerId); Assert.Equal(3, results[1].CustomerId); Assert.Equal(1, results[2].CustomerId); }
public void CanApplyOrderBy_WithNestedParameterAlias() { // Arrange var model = new ODataModelBuilder().Add_Customer_EntityType().Add_Customers_EntitySet().GetServiceModel(); var parser = new ODataQueryOptionParser( model, model.FindType("System.Web.OData.Builder.TestModels.Customer"), model.FindDeclaredNavigationSource("Default.Container.Customers"), new Dictionary<string, string> { { "$orderby", "@p1" }, { "@p2", "Name" }, { "@p1", "@p2" } }); var orderByOption = new OrderByQueryOption("@p1", new ODataQueryContext(model, typeof(Customer)), parser); var customers = (new List<Customer>{ new Customer { CustomerId = 1, Name = "Andy" }, new Customer { CustomerId = 2, Name = "Aaron" }, new Customer { CustomerId = 3, Name = "Alex" } }).AsQueryable(); // Act var results = orderByOption.ApplyTo(customers).ToArray(); // Assert Assert.Equal(2, results[0].CustomerId); Assert.Equal(3, results[1].CustomerId); Assert.Equal(1, results[2].CustomerId); }