diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 838af5d..ef0b2e1 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -12,12 +12,12 @@ jobs:
runs-on: windows-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup .NET Core
- uses: actions/setup-dotnet@v1
+ uses: actions/setup-dotnet@v4
with:
dotnet-version: 10.x
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 647bba8..f72f416 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -10,12 +10,12 @@ jobs:
runs-on: windows-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup .NET Core
- uses: actions/setup-dotnet@v1
+ uses: actions/setup-dotnet@v4
with:
dotnet-version: 10.x
diff --git a/AutoMapper.AspNetCore.OData.EF6/AutoMapper.AspNetCore.OData.EF6.csproj b/AutoMapper.AspNetCore.OData.EF6/AutoMapper.AspNetCore.OData.EF6.csproj
index a5e4b80..9b2373e 100644
--- a/AutoMapper.AspNetCore.OData.EF6/AutoMapper.AspNetCore.OData.EF6.csproj
+++ b/AutoMapper.AspNetCore.OData.EF6/AutoMapper.AspNetCore.OData.EF6.csproj
@@ -6,7 +6,7 @@
AutoMapper.AspNetCore.OData.EF6
Creates LINQ expressions from ODataQueryOptions and executes the query.
false
- Supporting AutoMapper v16 (EF Core only).
+ Marking obsolete methods (EF Core only).
linq expressions odata efcore
icon.png
https://github.com/AutoMapper/AutoMapper.Extensions.OData
diff --git a/AutoMapper.AspNetCore.OData.EFCore/AutoMapper.AspNetCore.OData.EFCore.csproj b/AutoMapper.AspNetCore.OData.EFCore/AutoMapper.AspNetCore.OData.EFCore.csproj
index 6f299d5..566a04c 100644
--- a/AutoMapper.AspNetCore.OData.EFCore/AutoMapper.AspNetCore.OData.EFCore.csproj
+++ b/AutoMapper.AspNetCore.OData.EFCore/AutoMapper.AspNetCore.OData.EFCore.csproj
@@ -6,7 +6,7 @@
AutoMapper.AspNetCore.OData.EFCore
Creates LINQ expressions from ODataQueryOptions and executes the query.
false
- Supporting AutoMapper v16 (EF Core only).
+ Marking obsolete methods (EF Core only).
linq expressions odata efcore
icon.png
https://github.com/AutoMapper/AutoMapper.Extensions.OData
@@ -30,7 +30,7 @@
-
+
diff --git a/AutoMapper.AspNetCore.OData.EFCore/QueryableExtensions.cs b/AutoMapper.AspNetCore.OData.EFCore/QueryableExtensions.cs
index 665fc35..1219c1c 100644
--- a/AutoMapper.AspNetCore.OData.EFCore/QueryableExtensions.cs
+++ b/AutoMapper.AspNetCore.OData.EFCore/QueryableExtensions.cs
@@ -13,6 +13,7 @@ namespace AutoMapper.AspNet.OData
{
public static class QueryableExtensions
{
+ [Obsolete("Use \"Task> GetQueryAsync(this IQueryable query, IMapper mapper, ODataQueryOptions options, QuerySettings querySettings = null)\" or \"IQueryable GetQuery(this IQueryable query, IMapper mapper, ODataQueryOptions options, QuerySettings querySettings = null)\" instead.")]
public static ICollection Get(this IQueryable query, IMapper mapper, ODataQueryOptions options, QuerySettings querySettings = null)
where TModel : class
{
@@ -31,6 +32,7 @@ public static ICollection Get(this IQueryable quer
);
}
+ [Obsolete("Use \"Task> GetQueryAsync(this IQueryable query, IMapper mapper, ODataQueryOptions options, QuerySettings querySettings = null)\" or \"IQueryable GetQuery(this IQueryable query, IMapper mapper, ODataQueryOptions options, QuerySettings querySettings = null)\" instead.")]
public static async Task> GetAsync(this IQueryable query, IMapper mapper, ODataQueryOptions options, QuerySettings querySettings = null)
where TModel : class
{
@@ -72,6 +74,7 @@ public static IQueryable GetQuery(this IQueryable
return query.GetQueryable(mapper, options, querySettings, filter);
}
+ [Obsolete("This method was meant for internal use. The equivalent GetQueryable methods are private.")]
public static ICollection Get(this IQueryable query, IMapper mapper,
Expression> filter = null,
Expression, IQueryable>> queryFunc = null,
@@ -81,7 +84,7 @@ public static ICollection Get(this IQueryable quer
query.GetDataQuery(mapper, filter, queryFunc, includeProperties).ToList()
).ToList();
-
+ [Obsolete("This method was meant for internal use. The equivalent GetQueryable methods are private.")]
public static async Task> GetAsync(this IQueryable query, IMapper mapper,
Expression> filter = null,
Expression, IQueryable>> queryFunc = null,
diff --git a/AutoMapper.OData.EFCore.Tests/ExpansionTests.cs b/AutoMapper.OData.EFCore.Tests/ExpansionTests.cs
index 8cf4519..9e78c26 100644
--- a/AutoMapper.OData.EFCore.Tests/ExpansionTests.cs
+++ b/AutoMapper.OData.EFCore.Tests/ExpansionTests.cs
@@ -218,7 +218,7 @@ public ExpansionTestsFixture()
),
ServiceLifetime.Transient
)
- .AddSingleton(new MapperConfiguration(cfg => cfg.AddMaps(typeof(GetTests).Assembly), new NullLoggerFactory()))
+ .AddSingleton(new MapperConfiguration(cfg => cfg.AddMaps(typeof(GetQueryTests).Assembly), new NullLoggerFactory()))
.AddTransient(sp => new Mapper(sp.GetRequiredService(), sp.GetService))
.AddTransient(sp => new ApplicationBuilder(sp))
.AddRouting()
diff --git a/AutoMapper.OData.EFCore.Tests/GetQuerySelectTests.cs b/AutoMapper.OData.EFCore.Tests/GetQuerySelectTests.cs
index ba9c456..998e593 100644
--- a/AutoMapper.OData.EFCore.Tests/GetQuerySelectTests.cs
+++ b/AutoMapper.OData.EFCore.Tests/GetQuerySelectTests.cs
@@ -214,7 +214,7 @@ public GetQuerySelectTestsFixture()
),
ServiceLifetime.Transient
)
- .AddSingleton(new MapperConfiguration(cfg => cfg.AddMaps(typeof(GetTests).Assembly), new NullLoggerFactory()))
+ .AddSingleton(new MapperConfiguration(cfg => cfg.AddMaps(typeof(GetQueryTests).Assembly), new NullLoggerFactory()))
.AddTransient(sp => new Mapper(sp.GetRequiredService(), sp.GetService))
.AddTransient(sp => new ApplicationBuilder(sp))
.AddRouting()
diff --git a/AutoMapper.OData.EFCore.Tests/GetQueryTests.cs b/AutoMapper.OData.EFCore.Tests/GetQueryTests.cs
index e241efd..9c39033 100644
--- a/AutoMapper.OData.EFCore.Tests/GetQueryTests.cs
+++ b/AutoMapper.OData.EFCore.Tests/GetQueryTests.cs
@@ -1,15 +1,22 @@
using AutoMapper.AspNet.OData;
+using AutoMapper.OData.EFCore.Tests.Binders;
using AutoMapper.OData.EFCore.Tests.Data;
using AutoMapper.OData.EFCore.Tests.Model;
using DAL.EFCore;
using Domain.OData;
using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.OData;
using Microsoft.AspNetCore.OData.Extensions;
using Microsoft.AspNetCore.OData.Query;
+using Microsoft.AspNetCore.OData.Query.Expressions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging.Abstractions;
+using Microsoft.OData.Edm;
+using Microsoft.OData.ModelBuilder;
+using Microsoft.OData.UriParser;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -2000,7 +2007,7 @@ public GetQueryTestsFixture()
),
ServiceLifetime.Transient
)
- .AddSingleton(new MapperConfiguration(cfg => cfg.AddMaps(typeof(GetTests).Assembly), new NullLoggerFactory()))
+ .AddSingleton(new MapperConfiguration(cfg => cfg.AddMaps(typeof(GetQueryTests).Assembly), new NullLoggerFactory()))
.AddTransient(sp => new Mapper(sp.GetRequiredService(), sp.GetService))
.AddTransient(sp => new ApplicationBuilder(sp))
.AddRouting()
@@ -2016,4 +2023,82 @@ public GetQueryTestsFixture()
internal IServiceProvider ServiceProvider;
}
+
+ public static class ODataHelpers
+ {
+ public static ODataQueryOptions GetODataQueryOptions(string queryString, IServiceProvider serviceProvider, string customNamespace = null, bool enableLowerCamelCase = false) where T : class
+ {
+ ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
+ if (customNamespace != null)
+ builder.Namespace = customNamespace;
+
+ if (enableLowerCamelCase)
+ builder.EnableLowerCamelCase();
+
+ builder.EntitySet(typeof(T).Name);
+ IEdmModel model = builder.GetEdmModel();
+ IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet(typeof(T).Name);
+ ODataPath path = new ODataPath(new EntitySetSegment(entitySet));
+
+ var oDataQueryOptions = new ODataQueryOptions
+ (
+ new ODataQueryContext(model, typeof(T), path),
+ BuildRequest(serviceProvider, model, new Uri(BASEADDRESS + queryString))
+ );
+
+ return oDataQueryOptions;
+ }
+
+ public static ODataQueryOptions GetODataQueryOptionsWithDuplicateEntityName(string queryString, IServiceProvider serviceProvider, string customNamespace = null)
+ {
+ ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
+ if (customNamespace != null)
+ builder.Namespace = customNamespace;
+
+ builder.EnableLowerCamelCase();
+
+ builder.EntitySet(typeof(X.CategoryModel).Name + "X");
+ builder.EntitySet(nameof(Model.CategoryModel));
+ IEdmModel model = builder.GetEdmModel();
+ IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet(typeof(Model.CategoryModel).Name);
+ ODataPath path = new ODataPath(new EntitySetSegment(entitySet));
+
+ var oDataQueryOptions = new ODataQueryOptions
+ (
+ new ODataQueryContext(model, typeof(Model.CategoryModel), path),
+ BuildRequest(serviceProvider, model, new Uri(BASEADDRESS + queryString))
+ );
+
+ return oDataQueryOptions;
+ }
+
+ static HttpRequest BuildRequest(IServiceProvider serviceProvider, IEdmModel model, Uri uri)
+ {
+ var request = new DefaultHttpContext()
+ {
+ RequestServices = serviceProvider
+ }.Request;
+
+ var oDataOptions = new ODataOptions().AddRouteComponents("key", model,
+ x => x.AddSingleton());
+ var (_, routeProvider) = oDataOptions.RouteComponents["key"];
+
+ request.ODataFeature().Services = routeProvider;
+
+ request.Method = "GET";
+ request.Host = new HostString(uri.Host, uri.Port);
+ request.Path = uri.LocalPath;
+ request.QueryString = new QueryString(uri.Query);
+
+ return request;
+ }
+
+ static readonly string BASEADDRESS = "http://localhost:16324";
+ }
+
+ internal class TestMvcCoreBuilder : IMvcCoreBuilder
+ {
+ public ApplicationPartManager PartManager { get; set; }
+ public IServiceCollection Services { get; set; }
+ }
}
diff --git a/AutoMapper.OData.EFCore.Tests/GetTests.cs b/AutoMapper.OData.EFCore.Tests/GetTests.cs
deleted file mode 100644
index c13c361..0000000
--- a/AutoMapper.OData.EFCore.Tests/GetTests.cs
+++ /dev/null
@@ -1,796 +0,0 @@
-using AutoMapper.AspNet.OData;
-using AutoMapper.OData.EFCore.Tests.Binders;
-using AutoMapper.OData.EFCore.Tests.Data;
-using DAL.EFCore;
-using Domain.OData;
-using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Mvc.ApplicationParts;
-using Microsoft.AspNetCore.OData;
-using Microsoft.AspNetCore.OData.Extensions;
-using Microsoft.AspNetCore.OData.Query;
-using Microsoft.AspNetCore.OData.Query.Expressions;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging.Abstractions;
-using Microsoft.OData.Edm;
-using Microsoft.OData.ModelBuilder;
-using Microsoft.OData.UriParser;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Xunit;
-
-namespace AutoMapper.OData.EFCore.Tests
-{
- public class GetTests : IClassFixture
- {
- private readonly GetTestsFixture _fixture;
-
- public GetTests(GetTestsFixture fixture)
- {
- _fixture = fixture;
- serviceProvider = _fixture.ServiceProvider;
- }
-
- #region Fields
- private readonly IServiceProvider serviceProvider;
- #endregion Fields
-
- [Fact]
- public async Task OpsTenantCreatedOnFilterServerUTCTimeZone()
- {
- var querySettings = new QuerySettings
- {
- ODataSettings = new ODataSettings
- {
- HandleNullPropagation = HandleNullPropagationOption.False,
- TimeZone = TimeZoneInfo.Utc
- }
- };
-
- string query = "/opstenant?$filter=CreatedDate eq 2012-12-12T00:00:00Z";
- Test(Get(query, querySettings: querySettings));
- Test(await GetAsync(query, querySettings: querySettings));
- Test(await GetUsingCustomNameSpace(query, querySettings: querySettings));
-
- query = "/opstenant?$filter=CreatedDate eq 2012-12-11T19:00:00-05:00";
- Test(Get(query, querySettings: querySettings));
- Test(await GetAsync(query, querySettings: querySettings));
- Test(await GetUsingCustomNameSpace(query, querySettings: querySettings));
-
- void Test(ICollection collection)
- {
- Assert.Equal(2, collection.Count);
- }
- }
-
- [Fact]
- public async Task OpsTenantCreatedOnFilterServerESTTimeZone()
- {
- var querySettings = new QuerySettings
- {
- ODataSettings = new ODataSettings
- {
- HandleNullPropagation = HandleNullPropagationOption.False,
- TimeZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time")
- }
- };
-
- string query = "/opstenant?$filter=CreatedDate eq 2012-12-12T05:00:00Z";
- Test(Get(query, querySettings: querySettings));
- Test(await GetAsync(query, querySettings: querySettings));
- Test(await GetUsingCustomNameSpace(query, querySettings: querySettings));
-
- query = "/opstenant?$filter=CreatedDate eq 2012-12-12T00:00:00-05:00";
- Test(Get(query, querySettings: querySettings));
- Test(await GetAsync(query, querySettings: querySettings));
- Test(await GetUsingCustomNameSpace(query, querySettings: querySettings));
-
- void Test(ICollection collection)
- {
- Assert.Equal(2, collection.Count);
- }
- }
-
- [Fact]
- public async Task OpsTenantExpandBuildingsFilterEqAndOrderBy()
- {
- string query = "/opstenant?$top=5&$expand=Buildings&$filter=Name eq 'One'&$orderby=Name desc";
- Test(Get(query));
- Test(await GetAsync(query));
- Test(await GetUsingCustomNameSpace(query));
-
- void Test(ICollection collection)
- {
- Assert.Single(collection);
- Assert.Equal(2, collection.First().Buildings.Count);
- Assert.Equal("One", collection.First().Name);
- }
- }
-
- [Fact]
- public async Task OpsTenantExpandBuildingsFilterNeAndOrderBy()
- {
- string query = "/opstenant?$top=5&$expand=Buildings&$filter=Name ne 'One'&$orderby=Name desc";
- Test(Get(query));
- Test(await GetAsync(query));
- Test(await GetUsingCustomNameSpace(query));
-
- void Test(ICollection collection)
- {
- Assert.Single(collection);
- Assert.Equal(3, collection.First().Buildings.Count);
- Assert.Equal("Two", collection.First().Name);
- }
- }
-
- [Fact]
- public async Task OpsTenantFilterEqNoExpand()
- {
- string query = "/opstenant?$filter=Name eq 'One'";
- Test(Get(query));
- Test(await GetAsync(query));
- Test(await GetUsingCustomNameSpace(query));
-
- void Test(ICollection collection)
- {
- Assert.Single(collection);
- Assert.Empty(collection.First().Buildings);
- Assert.Equal("One", collection.First().Name);
- }
- }
-
- [Fact]
- public async Task OpsTenantExpandBuildingsNoFilterAndOrderBy()
- {
- string query = "/opstenant?$top=5&$expand=Buildings&$orderby=Name desc";
- Test(Get(query));
- Test(await GetAsync(query));
- Test(await GetUsingCustomNameSpace(query));
-
- void Test(ICollection collection)
- {
- Assert.Equal(2, collection.Count);
- Assert.Equal(3, collection.First().Buildings.Count);
- Assert.Equal("Two", collection.First().Name);
- }
- }
-
- [Fact]
- public async Task OpsTenantNoExpandNoFilterAndOrderBy()
- {
- string query = "/opstenant?$orderby=Name desc";
- Test(Get(query));
- Test(await GetAsync(query));
- Test(await GetUsingCustomNameSpace(query));
-
- void Test(ICollection collection)
- {
- Assert.Equal(2, collection.Count);
- Assert.Empty(collection.First().Buildings);
- Assert.Equal("Two", collection.First().Name);
- }
- }
-
- [Fact]
- public async Task OpsTenantNoExpandFilterEqAndOrderBy()
- {
- string query = "/opstenant?$top=5&$filter=Name eq 'One'&$orderby=Name desc";
- Test(Get(query));
- Test(await GetAsync(query));
- Test(await GetUsingCustomNameSpace(query));
-
- void Test(ICollection collection)
- {
- Assert.Single(collection);
- Assert.Empty(collection.First().Buildings);
- Assert.Equal("One", collection.First().Name);
- }
- }
-
- [Fact]
- public async Task OpsTenantExpandBuildingsExpandBuilderExpandCityFilterNeAndOrderBy()
- {
- string query = "/opstenant?$top=5&$expand=Buildings($expand=Builder($expand=City))&$filter=Name ne 'One'&$orderby=Name desc";
- Test(Get(query));
- Test(await GetAsync(query));
- Test(await GetUsingCustomNameSpace(query));
-
- void Test(ICollection collection)
- {
- Assert.Single(collection);
- Assert.Equal(3, collection.First().Buildings.Count);
- Assert.NotNull(collection.First().Buildings.First().Builder);
- Assert.NotNull(collection.First().Buildings.First().Builder.City);
- Assert.Equal("Two", collection.First().Name);
- }
- }
-
- [Fact]
- public async Task BuildingExpandBuilderTenantFilterEqAndOrderBy()
- {
- string query = "/corebuilding?$top=5&$expand=Builder,Tenant&$filter=Name eq 'One L1'";
- Test(Get(query));
- Test(await GetAsync(query));
- Test(await GetUsingCustomNameSpace(query));
-
- void Test(ICollection collection)
- {
- Assert.Single(collection);
- Assert.Equal("Sam", collection.First().Builder.Name);
- Assert.Equal("One", collection.First().Tenant.Name);
- Assert.Equal("One L1", collection.First().Name);
- }
- }
-
- [Fact]
- public async Task BuildingExpandBuilderTenantFilterOnNestedPropertyAndOrderBy()
- {
- string query = "/corebuilding?$top=5&$expand=Builder,Tenant&$filter=Builder/Name eq 'Sam'&$orderby=Name asc";
- Test(Get(query));
- Test(await GetAsync(query));
- Test(await GetUsingCustomNameSpace(query));
-
- void Test(ICollection collection)
- {
- Assert.Equal(2, collection.Count);
- Assert.Equal("Sam", collection.First().Builder.Name);
- Assert.Equal("One", collection.First().Tenant.Name);
- Assert.Equal("One L1", collection.First().Name);
- }
- }
-
- [Fact]
- public async Task BuildingExpandBuilderTenantExpandCityFilterOnPropertyAndOrderBy()
- {
- string query = "/corebuilding?$top=5&$expand=Builder($expand=City),Tenant&$filter=Name ne 'One L2'&$orderby=Name desc";
- Test(Get(query));
- Test(await GetAsync(query));
- Test(await GetUsingCustomNameSpace(query));
-
- void Test(ICollection collection)
- {
- Assert.Equal(4, collection.Count);
- Assert.NotNull(collection.First().Builder.City);
- Assert.Equal("Two L3", collection.First().Name);
- }
- }
-
- [Fact]
- public async Task BuildingExpandBuilderTenantExpandCityFilterOnNestedNestedPropertyWithCount()
- {
- string query = "/corebuilding?$top=5&$expand=Builder($expand=City),Tenant&$filter=Builder/City/Name eq 'Leeds'&$count=true";
- ODataQueryOptions options = ODataHelpers.GetODataQueryOptions
- (
- query,
- serviceProvider
- );
- Test(Get(query, options));
- Test(await GetAsync(query, options));
- Test
- (
- await GetUsingCustomNameSpace
- (
- query,
- ODataHelpers.GetODataQueryOptions
- (
- query,
- serviceProvider,
- "com.FooBar"
- )
- )
- );
-
- void Test(ICollection collection)
- {
- Assert.Equal(2, options.Request.ODataFeature().TotalCount);
- Assert.Equal(2, collection.Count);
- Assert.Equal("Leeds", collection.First().Builder.City.Name);
- }
- }
-
- [Fact]
- public async Task BuildingExpandBuilderTenantExpandCityOrderByName()
- {
- string query = "/corebuilding?$top=5&$expand=Builder($expand=City),Tenant&$orderby=Name desc";
- Test(Get(query));
- Test(await GetAsync(query));
- Test(await GetUsingCustomNameSpace(query));
-
- void Test(ICollection collection)
- {
- Assert.Equal(5, collection.Count);
- Assert.Equal("Leeds", collection.First().Builder.City.Name);
- }
- }
-
- [Fact]
- public async Task BuildingExpandBuilderTenantExpandCityOrderByNameThenByIdentity()
- {
- string query = "/corebuilding?$top=5&$expand=Builder($expand=City),Tenant&$orderby=Name desc,Identity";
- Test(Get(query));
- Test(await GetAsync(query));
- Test(await GetUsingCustomNameSpace(query));
-
- void Test(ICollection collection)
- {
- Assert.Equal(5, collection.Count);
- Assert.Equal("Leeds", collection.First().Builder.City.Name);
- }
- }
-
- [Fact]
- public async Task BuildingExpandBuilderTenantExpandCityOrderByBuilderName()
- {
- string query = "/corebuilding?$top=5&$expand=Builder($expand=City),Tenant&$orderby=Builder/Name";
- Test(Get(query));
- Test(await GetAsync(query));
- Test(await GetUsingCustomNameSpace(query));
-
- void Test(ICollection collection)
- {
- Assert.Equal(5, collection.Count);
- Assert.Equal("London", collection.First().Builder.City.Name);
- Assert.Equal("Two L1", collection.First().Name);
- }
- }
-
- [Fact]
- public async Task BuildingExpandBuilderTenantExpandCityOrderByBuilderNameSkip3Take1WithCount()
- {
- string query = "/corebuilding?$skip=4&$top=1&$expand=Builder($expand=City),Tenant&$orderby=Name desc,Identity&$count=true";
- ODataQueryOptions options = ODataHelpers.GetODataQueryOptions
- (
- query,
- serviceProvider
- );
- Test(Get(query, options));
- Test(await GetAsync(query, options));
- Test(await GetUsingCustomNameSpace(query, options));
-
- void Test(ICollection collection)
- {
- Assert.Equal(5, options.Request.ODataFeature().TotalCount);
- Assert.Single(collection);
- Assert.Equal("London", collection.First().Builder.City.Name);
- Assert.Equal("One L1", collection.First().Name);
- }
- }
-
- [Fact]
- public async Task BuildingExpandBuilderTenantExpandCityOrderByBuilderNameSkip3Take1NoCount()
- {
- string query = "/corebuilding?$skip=4&$top=1&$expand=Builder($expand=City),Tenant&$orderby=Name desc,Identity";
- ODataQueryOptions options = ODataHelpers.GetODataQueryOptions
- (
- query,
- serviceProvider
- );
-
- Test(Get(query, options));
- Test(await GetAsync(query, options));
- Test(await GetUsingCustomNameSpace(query, options));
-
- void Test(ICollection collection)
- {
- Assert.Null(options.Request.ODataFeature().TotalCount);
- Assert.Single(collection);
- Assert.Equal("London", collection.First().Builder.City.Name);
- Assert.Equal("One L1", collection.First().Name);
- }
- }
-
- [Fact]
- public async Task BuildingSelectNameWithoutOrderWithoutTop()
- {
- string query = "/corebuilding?$select=Name";
- Test(Get(query));
- Test(await GetAsync(query));
- Test(await GetUsingCustomNameSpace(query));
-
- void Test(ICollection collection)
- {
- Assert.Equal(5, collection.Count);
- }
- }
-
- [Fact]
- public async Task BuildingWithoutTopAndPageSize()
- {
- string query = "/corebuilding";
- Test(Get(query));
- Test(await GetAsync(query));
- Test(await GetUsingCustomNameSpace(query));
-
- void Test(ICollection collection)
- {
- Assert.Equal(5, collection.Count);
- }
- }
-
- [Fact]
- public async Task BuildingWithTopOnly()
- {
- string query = "/corebuilding?$top=3";
- Test(Get(query));
- Test(await GetAsync(query));
- Test(await GetUsingCustomNameSpace(query));
-
- void Test(ICollection collection)
- {
- Assert.Equal(3, collection.Count);
- }
- }
-
- [Fact]
- public async Task BuildingWithPageSizeOnly()
- {
- string query = "/corebuilding";
- var querySettings = new QuerySettings { ODataSettings = new ODataSettings { HandleNullPropagation = HandleNullPropagationOption.False, PageSize = 2 } };
- Test(Get(query, querySettings: querySettings));
- Test(await GetAsync(query, querySettings: querySettings));
- Test(await GetUsingCustomNameSpace(query, querySettings: querySettings));
-
- void Test(ICollection collection)
- {
- Assert.Equal(2, collection.Count);
- }
- }
-
- [Fact]
- public async Task BuildingWithTopAndSmallerPageSize()
- {
- string query = "/corebuilding?$top=3";
- var querySettings = new QuerySettings { ODataSettings = new ODataSettings { HandleNullPropagation = HandleNullPropagationOption.False, PageSize = 2 } };
- Test(Get(query, querySettings: querySettings));
- Test(await GetAsync(query, querySettings: querySettings));
- Test(await GetUsingCustomNameSpace(query, querySettings: querySettings));
-
- void Test(ICollection collection)
- {
- Assert.Equal(2, collection.Count);
- }
- }
-
- [Fact]
- public async Task BuildingWithTopAndLargerPageSize()
- {
- string query = "/corebuilding?$top=3";
- var querySettings = new QuerySettings { ODataSettings = new ODataSettings { HandleNullPropagation = HandleNullPropagationOption.False, PageSize = 4 } };
- Test(Get(query, querySettings: querySettings));
- Test(await GetAsync(query, querySettings: querySettings));
- Test(await GetUsingCustomNameSpace(query, querySettings: querySettings));
-
- void Test(ICollection collection)
- {
- Assert.Equal(3, collection.Count);
- }
- }
-
- [Fact]
- public async Task BuildingWithTopAndSmallerPageSizeNextLink()
- {
- int pageSize = 2;
- string query = "/corebuilding?$top=3";
- var querySettings = new QuerySettings { ODataSettings = new ODataSettings { HandleNullPropagation = HandleNullPropagationOption.False, PageSize = pageSize } };
- ODataQueryOptions options = ODataHelpers.GetODataQueryOptions
- (
- query,
- serviceProvider
- );
-
- Test(Get(query, options, querySettings));
- Test(await GetAsync(query, options, querySettings));
- Test
- (
- await GetUsingCustomNameSpace
- (
- query,
- ODataHelpers.GetODataQueryOptions
- (
- query,
- serviceProvider,
- "com.FooBar"
- ),
- querySettings
- )
- );
-
- void Test(ICollection collection)
- {
- Assert.Equal(2, collection.Count);
-
- Uri nextPageLink = options.Request.ODataFeature().NextLink;
- Assert.NotNull(nextPageLink);
- Assert.Equal("localhost:16324/corebuilding?$top=1&$skip=2", nextPageLink.AbsoluteUri);
- Assert.Contains("$top=1", nextPageLink.Query);
- Assert.Contains("$skip=2", nextPageLink.Query);
- }
- }
-
- [Fact]
- public async Task BuildingWithTopAndLargerPageSizeNextLink()
- {
- int pageSize = 4;
- string query = "/corebuilding?$top=3";
- var querySettings = new QuerySettings { ODataSettings = new ODataSettings { HandleNullPropagation = HandleNullPropagationOption.False, PageSize = pageSize } };
- ODataQueryOptions options = ODataHelpers.GetODataQueryOptions
- (
- query,
- serviceProvider
- );
-
- Test(Get(query, options, querySettings));
- Test(await GetAsync(query, options, querySettings));
- Test
- (
- await GetUsingCustomNameSpace
- (
- query,
- ODataHelpers.GetODataQueryOptions
- (
- query,
- serviceProvider,
- "com.FooBar"
- ),
- querySettings
- )
- );
-
- void Test(ICollection collection)
- {
- Assert.Equal(3, collection.Count);
- Assert.Null(options.Request.ODataFeature().NextLink);
- }
- }
-
- [Fact]
- public async Task OpsTenantOrderByCountOfReference()
- {
- string query = "/opstenant?$expand=Buildings&$orderby=Buildings/$count desc";
- Test(Get(query));
- Test(await GetAsync(query));
- Test(await GetUsingCustomNameSpace(query));
-
- void Test(ICollection collection)
- {
- Assert.Equal(2, collection.Count);
- Assert.NotNull(collection.First().Buildings);
- Assert.Equal("Two", collection.First().Name);
- Assert.Equal(3, collection.First().Buildings.Count);
- Assert.Equal(2, collection.Last().Buildings.Count);
- }
- }
-
- [Fact]
- public async Task OpsTenantOrderByFilteredCount()
- {
- string query = "/opstenant?$expand=Buildings&$orderby=Buildings/$count($filter=Name eq 'One L1') desc";
- Test(Get(query));
- Test(await GetAsync(query));
- Test(await GetUsingCustomNameSpace(query));
-
- void Test(ICollection collection)
- {
- Assert.Equal(2, collection.Count);
- Assert.NotNull(collection.First().Buildings);
- Assert.Equal("One", collection.First().Name);
- Assert.Equal(2, collection.First().Buildings.Count);
- Assert.Equal(3, collection.Last().Buildings.Count);
- }
- }
-
- //Exception: 'The Include path 'Mandator->Buildings' results in a cycle.
- //Cycles are not allowed in no-tracking queries. Either use a tracking query or remove the cycle.'
- [Fact]
- public async Task CoreBuildingOrderByCountOfChildReferenceOfReference()
- {
- string query = "/corebuilding?$expand=Tenant($expand=Buildings)&$orderby=Tenant/Buildings/$count desc";
- Test(Get(query));
- Test(await GetAsync(query));
- Test(await GetUsingCustomNameSpace(query));
-
- void Test(ICollection collection)
- {
- Assert.Equal(5, collection.Count);
- Assert.NotNull(collection.First().Tenant.Buildings);
- Assert.Equal(3, collection.First().Tenant.Buildings.Count);
- Assert.Equal(2, collection.Last().Tenant.Buildings.Count);
- }
- }
-
- [Fact]
- public async Task CoreBuildingOrderByPropertyOfChildReferenceOfReference()
- {
- string query = "/corebuilding?$expand=Builder($expand=City)&$orderby=Builder/City/Name desc";
- Test(Get(query));
- Test(await GetAsync(query));
- Test(await GetUsingCustomNameSpace(query));
-
- void Test(ICollection collection)
- {
- Assert.Equal(5, collection.Count);
- Assert.NotNull(collection.First().Builder.City);
- Assert.Equal("London", collection.First().Builder.City.Name);
- Assert.Equal("Leeds", collection.Last().Builder.City.Name);
- }
- }
-
- [Fact]
- public async Task CancellationThrowsException()
- {
- var cancelledToken = new CancellationTokenSource(TimeSpan.Zero).Token;
- await Assert.ThrowsAnyAsync(() => GetAsync("/corebuilding", querySettings: new QuerySettings { AsyncSettings = new AsyncSettings { CancellationToken = cancelledToken } }));
- }
-
- private ICollection Get(string query, ODataQueryOptions options = null, QuerySettings querySettings = null, string customNamespace = null) where TModel : class where TData : class
- {
- return DoGet
- (
- serviceProvider.GetRequiredService(),
- serviceProvider.GetRequiredService()
- );
-
- ICollection DoGet(IMapper mapper, MyDbContext context)
- {
- return context.Set().Get
- (
- mapper,
- options ?? GetODataQueryOptions(query, customNamespace),
- querySettings
- );
- }
- }
-
- private async Task> GetAsync(string query, ODataQueryOptions options = null, QuerySettings querySettings = null, string customNamespace = null) where TModel : class where TData : class
- {
- return await DoGet
- (
- serviceProvider.GetRequiredService(),
- serviceProvider.GetRequiredService()
- );
-
- async Task> DoGet(IMapper mapper, MyDbContext context)
- {
- return await context.Set().GetAsync
- (
- mapper,
- options ?? GetODataQueryOptions(query, customNamespace),
- querySettings
- );
- }
- }
-
- private Task> GetUsingCustomNameSpace(string query,
- ODataQueryOptions options = null, QuerySettings querySettings = null) where TModel : class where TData : class
- => GetAsync(query, options, querySettings, "com.FooBar");
-
- private ODataQueryOptions GetODataQueryOptions(string query, string customNamespace = null) where TModel : class
- {
- return ODataHelpers.GetODataQueryOptions
- (
- query,
- serviceProvider,
- customNamespace
- );
- }
- }
-
- public static class ODataHelpers
- {
- public static ODataQueryOptions GetODataQueryOptions(string queryString, IServiceProvider serviceProvider, string customNamespace = null, bool enableLowerCamelCase = false) where T : class
- {
- ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
- if (customNamespace != null)
- builder.Namespace = customNamespace;
-
- if (enableLowerCamelCase)
- builder.EnableLowerCamelCase();
-
- builder.EntitySet(typeof(T).Name);
- IEdmModel model = builder.GetEdmModel();
- IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet(typeof(T).Name);
- ODataPath path = new ODataPath(new EntitySetSegment(entitySet));
-
- var oDataQueryOptions = new ODataQueryOptions
- (
- new ODataQueryContext(model, typeof(T), path),
- BuildRequest(serviceProvider, model, new Uri(BASEADDRESS + queryString))
- );
-
- return oDataQueryOptions;
- }
-
- public static ODataQueryOptions GetODataQueryOptionsWithDuplicateEntityName(string queryString, IServiceProvider serviceProvider, string customNamespace = null)
- {
- ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
- if (customNamespace != null)
- builder.Namespace = customNamespace;
-
- builder.EnableLowerCamelCase();
-
- builder.EntitySet(typeof(X.CategoryModel).Name + "X");
- builder.EntitySet(nameof(Model.CategoryModel));
- IEdmModel model = builder.GetEdmModel();
- IEdmEntitySet entitySet = model.EntityContainer.FindEntitySet(typeof(Model.CategoryModel).Name);
- ODataPath path = new ODataPath(new EntitySetSegment(entitySet));
-
- var oDataQueryOptions = new ODataQueryOptions
- (
- new ODataQueryContext(model, typeof(Model.CategoryModel), path),
- BuildRequest(serviceProvider, model, new Uri(BASEADDRESS + queryString))
- );
-
- return oDataQueryOptions;
- }
-
- static HttpRequest BuildRequest(IServiceProvider serviceProvider, IEdmModel model, Uri uri)
- {
- var request = new DefaultHttpContext()
- {
- RequestServices = serviceProvider
- }.Request;
-
- var oDataOptions = new ODataOptions().AddRouteComponents("key", model,
- x => x.AddSingleton());
- var (_, routeProvider) = oDataOptions.RouteComponents["key"];
-
- request.ODataFeature().Services = routeProvider;
-
- request.Method = "GET";
- request.Host = new HostString(uri.Host, uri.Port);
- request.Path = uri.LocalPath;
- request.QueryString = new QueryString(uri.Query);
-
- return request;
- }
-
- static readonly string BASEADDRESS = "http://localhost:16324";
- }
-
- internal class TestMvcCoreBuilder : IMvcCoreBuilder
- {
- public ApplicationPartManager PartManager { get; set; }
- public IServiceCollection Services { get; set; }
- }
-
- public class GetTestsFixture
- {
- public GetTestsFixture()
- {
- IServiceCollection services = new ServiceCollection();
- IMvcCoreBuilder builder = new TestMvcCoreBuilder
- {
- Services = services
- };
-
- builder.AddOData();
- services.AddDbContext
- (
- options => options.UseSqlServer
- (
- @"Server=(localdb)\mssqllocaldb;Database=GetTestsDatabase;ConnectRetryCount=0",
- options => options.EnableRetryOnFailure()
- ),
- ServiceLifetime.Transient
- )
- .AddSingleton(new MapperConfiguration(cfg => cfg.AddMaps(typeof(GetTests).Assembly), new NullLoggerFactory()))
- .AddTransient(sp => new Mapper(sp.GetRequiredService(), sp.GetService))
- .AddTransient(sp => new ApplicationBuilder(sp))
- .AddRouting()
- .AddLogging();
-
- ServiceProvider = services.BuildServiceProvider();
-
- MyDbContext context = ServiceProvider.GetRequiredService();
- context.Database.EnsureDeleted();
- context.Database.EnsureCreated();
- DatabaseInitializer.SeedDatabase(context);
- }
-
- internal IServiceProvider ServiceProvider;
- }
-}