From 4e747d1b5d26231333364d8696d1d5b051bd134e Mon Sep 17 00:00:00 2001 From: Blaise Taylor Date: Wed, 1 Apr 2026 10:30:48 -0400 Subject: [PATCH] Removing obsolete methods and using the latest expression mapping version. --- .github/workflows/ci.yml | 6 - .github/workflows/release.yml | 6 - .../AutoMapper.AspNetCore.OData.EFCore.csproj | 12 +- .../EFCoreLinqExtensions.cs | 71 ------------ .../FilterHelper.cs | 3 - .../LinqExtensions.cs | 10 -- .../QueryableExtensions.cs | 82 -------------- AutoMapper.Extensions.OData.sln | 28 +---- .../AutoMapper.OData.EFCore.Tests.csproj | 14 +-- .../ExpressionBuilder.Tests.csproj | 12 +- ExpressionBuilder.Tests/FilterTests.cs | 5 +- MigrationTool/MigrationContext.cs | 2 +- README.md | 5 +- SeedDatabase/appsettings.json | 2 +- Web.Tests/GetTests.cs | 104 ++++++------------ Web.Tests/Web.Tests.csproj | 12 +- .../WebAPI.OData.EFCore.csproj | 5 +- WebAPI.OData.EFCore/appsettings.json | 2 +- 18 files changed, 69 insertions(+), 312 deletions(-) delete mode 100644 AutoMapper.AspNetCore.OData.EFCore/EFCoreLinqExtensions.cs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ef0b2e1..57fd492 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,9 +42,3 @@ jobs: PROJECT_NAME: AutoMapper.AspNetCore.OData.EFCore run: ./Pack_Push.ps1 shell: pwsh - - - name: Pack and push AutoMapper.AspNetCore.OData.EF6 - env: - PROJECT_NAME: AutoMapper.AspNetCore.OData.EF6 - run: ./Pack_Push.ps1 - shell: pwsh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f72f416..88826cc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -40,9 +40,3 @@ jobs: PROJECT_NAME: AutoMapper.AspNetCore.OData.EFCore run: ./Pack_Push.ps1 shell: pwsh - - - name: Pack and push AutoMapper.AspNetCore.OData.EF6 - env: - PROJECT_NAME: AutoMapper.AspNetCore.OData.EF6 - run: ./Pack_Push.ps1 - shell: pwsh diff --git a/AutoMapper.AspNetCore.OData.EFCore/AutoMapper.AspNetCore.OData.EFCore.csproj b/AutoMapper.AspNetCore.OData.EFCore/AutoMapper.AspNetCore.OData.EFCore.csproj index 566a04c..0f007ea 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 - Marking obsolete methods (EF Core only). + Removing obsolete methods and using the latest version of AutoMapper.Extensions.ExpressionMapping. Ending maintenance for AutoMapper.AspNetCore.OData.EF6. linq expressions odata efcore icon.png https://github.com/AutoMapper/AutoMapper.Extensions.OData @@ -30,8 +30,8 @@ - - + + all @@ -41,15 +41,15 @@ - + - + - + diff --git a/AutoMapper.AspNetCore.OData.EFCore/EFCoreLinqExtensions.cs b/AutoMapper.AspNetCore.OData.EFCore/EFCoreLinqExtensions.cs deleted file mode 100644 index 1b1d0c5..0000000 --- a/AutoMapper.AspNetCore.OData.EFCore/EFCoreLinqExtensions.cs +++ /dev/null @@ -1,71 +0,0 @@ -using LogicBuilder.Expressions.Utils; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Query; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using System.Reflection; - -namespace AutoMapper.AspNet.OData -{ - public static class EFCoreLinqExtensions - { - /// - /// Creates a list of Include expressions from a list of properties. Each property may include child and granchild properties. - /// - /// - /// - /// - public static ICollection, IIncludableQueryable>>> BuildIncludesExpressionCollection(this IEnumerable includes) where T : class - => (includes == null || includes.Count() == 0) - ? null - : includes.Select(i => i.BuildIncludeExpression()).ToList(); - - /// - /// Creates an Include expression from a property. The property may include child and granchild properties. - /// - /// - /// - /// - public static Expression, IIncludableQueryable>> BuildIncludeExpression(this string include) where T : class - { - if (string.IsNullOrEmpty(include)) return null; - - ParameterExpression param = Expression.Parameter(typeof(IQueryable), "q"); - MethodCallExpression mce = param.GetInclude(include); - return Expression.Lambda, IIncludableQueryable>>(mce, param); - } - - /// - /// Creates an include method call expression to be invoked on an expression e.g. (parameter, member, method call) of type IQueryable. - /// - /// - /// - /// - /// - /// - public static MethodCallExpression GetInclude(this Expression expression, string include) - { - if (string.IsNullOrEmpty(include)) return null; - ICollection includes = include.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries); - Type parentType = typeof(TSource); - - return includes.Aggregate(null, (MethodCallExpression mce, string next) => - { - LambdaExpression selectorExpression = next.GetTypedSelector(parentType); - MemberInfo mInfo = parentType.GetMemberInfo(next); - - mce = mce == null - //The Include espression takes two arguments. The parameter (object being extended by the helper method) and the lambda expression for the property selector - ? Expression.Call(typeof(EntityFrameworkQueryableExtensions), "Include", new Type[] { parentType, mInfo.GetMemberType() }, expression, selectorExpression) - //The ThenInclude espression takes two arguments. The resulting method call expression from Include and the lambda expression for the property selector - : Expression.Call(typeof(EntityFrameworkQueryableExtensions), "ThenInclude", new Type[] { typeof(TSource), parentType, mInfo.GetMemberType() }, mce, selectorExpression); - - parentType = mInfo.GetMemberType().GetCurrentType();//new previous property to include members from. - - return mce; - }); - } - } -} diff --git a/AutoMapper.AspNetCore.OData.EFCore/FilterHelper.cs b/AutoMapper.AspNetCore.OData.EFCore/FilterHelper.cs index c967ba1..d1a5310 100644 --- a/AutoMapper.AspNetCore.OData.EFCore/FilterHelper.cs +++ b/AutoMapper.AspNetCore.OData.EFCore/FilterHelper.cs @@ -166,9 +166,6 @@ private IExpressionPart GetAnyNodeFilterPart(AnyNode anyNode) private IExpressionPart GetAllNodeFilterPart(AllNode allNode) { - if (allNode.Body == null || IsTrueConstantExpression(allNode.Body)) - return new AllOperator(GetFilterPart(allNode.Source)); - //Creating filter part for method call expression with a filter //e.g. $it.Property.ChildCollection.Any(c => c.Active); return new AllOperator diff --git a/AutoMapper.AspNetCore.OData.EFCore/LinqExtensions.cs b/AutoMapper.AspNetCore.OData.EFCore/LinqExtensions.cs index bf0f88d..9704cac 100644 --- a/AutoMapper.AspNetCore.OData.EFCore/LinqExtensions.cs +++ b/AutoMapper.AspNetCore.OData.EFCore/LinqExtensions.cs @@ -425,12 +425,6 @@ public static LambdaExpression MakeLambdaExpression(this ParameterExpression par return Expression.Lambda(delegateType, body, param);//Resulting lambda expression for the selector. } - [Obsolete("\"Expression GetOrderByCountCall(this Expression expression, CountNode countNode, string methodName, ODataQueryContext context, string selectorParameterName = \"a\")\"")] - public static Expression GetOrderByCountCall(this Expression expression, CountNode countNode, string methodName, string selectorParameterName = "a") - { - return expression.GetOrderByCountCall(countNode, methodName, null, selectorParameterName); - } - public static Expression GetOrderByCountCall(this Expression expression, CountNode countNode, string methodName, ODataQueryContext context, string selectorParameterName = "a") { Type sourceType = LogicBuilder.Expressions.Utils.TypeExtensions.GetUnderlyingElementType(expression); @@ -624,10 +618,6 @@ bool HasQuery() }); } - [Obsolete("\"LambdaExpression GetFilterExpression(this FilterClause filterClause, Type type, ODataQueryContext context)\"")] - public static LambdaExpression GetFilterExpression(this FilterClause filterClause, Type type) - => filterClause.GetFilterExpression(type, null); - public static LambdaExpression GetFilterExpression(this FilterClause filterClause, Type type, ODataQueryContext context) { var parameters = new Dictionary(); diff --git a/AutoMapper.AspNetCore.OData.EFCore/QueryableExtensions.cs b/AutoMapper.AspNetCore.OData.EFCore/QueryableExtensions.cs index 1219c1c..4af01d0 100644 --- a/AutoMapper.AspNetCore.OData.EFCore/QueryableExtensions.cs +++ b/AutoMapper.AspNetCore.OData.EFCore/QueryableExtensions.cs @@ -13,44 +13,6 @@ 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 - { - Expression> filter = options.ToFilterExpression( - querySettings?.ODataSettings?.HandleNullPropagation ?? HandleNullPropagationOption.False, - querySettings?.ODataSettings?.TimeZone, - querySettings?.ODataSettings?.EnableConstantParameterization ?? true); - - query.ApplyOptions(mapper, filter, options, querySettings); - return query.Get - ( - mapper, - filter, - options.GetQueryableExpression(querySettings?.ODataSettings), - options.SelectExpand.GetIncludes().BuildIncludesExpressionCollection()?.ToList() - ); - } - - [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 - { - Expression> filter = options.ToFilterExpression( - querySettings?.ODataSettings?.HandleNullPropagation ?? HandleNullPropagationOption.False, - querySettings?.ODataSettings?.TimeZone, - querySettings?.ODataSettings?.EnableConstantParameterization ?? true); - await query.ApplyOptionsAsync(mapper, filter, options, querySettings); - return await query.GetAsync - ( - mapper, - filter, - options.GetQueryableExpression(querySettings?.ODataSettings), - options.SelectExpand.GetIncludes().BuildIncludesExpressionCollection()?.ToList(), - querySettings?.AsyncSettings - ); - } - public static async Task> GetQueryAsync(this IQueryable query, IMapper mapper, ODataQueryOptions options, QuerySettings querySettings = null) where TModel : class { @@ -74,32 +36,6 @@ 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, - ICollection, IIncludableQueryable>>> includeProperties = null) - => mapper.Map, IEnumerable> - ( - 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, - ICollection, IIncludableQueryable>>> includeProperties = null, - AsyncSettings asyncSettings = null) - => mapper.Map, IEnumerable> - ( - await query - .GetDataQuery(mapper, filter, queryFunc, includeProperties) - .ToListAsync - ( - asyncSettings?.CancellationToken ?? default - ) - ).ToList(); - public static async Task ApplyOptionsAsync(this IQueryable query, IMapper mapper, Expression> filter, ODataQueryOptions options, QuerySettings querySettings) { ApplyOptions(options, querySettings); @@ -107,24 +43,6 @@ public static async Task ApplyOptionsAsync(this IQueryable options.AddCountOptionsResult(await query.QueryLongCountAsync(mapper, filter, querySettings?.AsyncSettings?.CancellationToken ?? default)); } - private static IQueryable GetDataQuery(this IQueryable query, IMapper mapper, - Expression> filter = null, - Expression, IQueryable>> queryFunc = null, - ICollection, IIncludableQueryable>>> includeProperties = null) - { - Expression> f = mapper.MapExpression>>(filter); - Func, IQueryable> mappedQueryFunc = mapper.MapExpression, IQueryable>>>(queryFunc)?.Compile(); - ICollection, IIncludableQueryable>>> includes = mapper.MapIncludesList, IIncludableQueryable>>>(includeProperties); - - if (filter != null) - query = query.Where(f); - - if (includes != null) - query = includes.Select(i => i.Compile()).Aggregate(query, (q, next) => q = next(q)); - - return mappedQueryFunc != null ? mappedQueryFunc(query) : query; - } - private static IQueryable GetQueryable(this IQueryable query, IMapper mapper, ODataQueryOptions options, diff --git a/AutoMapper.Extensions.OData.sln b/AutoMapper.Extensions.OData.sln index 052ff2f..9c59675 100644 --- a/AutoMapper.Extensions.OData.sln +++ b/AutoMapper.Extensions.OData.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 18 -VisualStudioVersion = 18.1.11312.151 d18.0 +VisualStudioVersion = 18.1.11312.151 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoMapper.AspNetCore.OData.EFCore", "AutoMapper.AspNetCore.OData.EFCore\AutoMapper.AspNetCore.OData.EFCore.csproj", "{8E4C661E-C58A-4515-9CBF-F58D9D6E941D}" EndProject @@ -15,8 +15,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DAL.EFCore", "DAL.EFCore\DA EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Domain.OData", "Domain.OData\Domain.OData.csproj", "{D5EC56A8-21AB-464D-BCA5-38F672560207}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoMapper.AspNetCore.OData.EF6", "AutoMapper.AspNetCore.OData.EF6\AutoMapper.AspNetCore.OData.EF6.csproj", "{7836C0FC-B1FD-44FF-9643-AC0104419A80}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebAPI.OData.EFCore", "WebAPI.OData.EFCore\WebAPI.OData.EFCore.csproj", "{5D285685-62D1-4B1E-B469-18C1715471FF}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{D2A273B8-0229-4121-8189-175960E7749D}" @@ -37,12 +35,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MigrationTool", "MigrationT EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SeedDatabase", "SeedDatabase\SeedDatabase.csproj", "{CE492720-2000-4533-93AF-5AA71A65D305}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoMapper.OData.EF6.Tests", "AutoMapper.OData.EF6.Tests\AutoMapper.OData.EF6.Tests.csproj", "{BF11CF7F-0424-46F7-A60E-B614525C68C7}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebAPI.OData.EF6", "WebAPI.OData.EF6\WebAPI.OData.EF6.csproj", "{4C069416-CF7B-45C7-8C8F-B3D24DC16D01}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DAL.EF6", "DAL.EF6\DAL.EF6.csproj", "{8139DB48-8A96-405A-9B02-44C4AEF79FD0}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -65,10 +57,6 @@ Global {D5EC56A8-21AB-464D-BCA5-38F672560207}.Debug|Any CPU.Build.0 = Debug|Any CPU {D5EC56A8-21AB-464D-BCA5-38F672560207}.Release|Any CPU.ActiveCfg = Release|Any CPU {D5EC56A8-21AB-464D-BCA5-38F672560207}.Release|Any CPU.Build.0 = Release|Any CPU - {7836C0FC-B1FD-44FF-9643-AC0104419A80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7836C0FC-B1FD-44FF-9643-AC0104419A80}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7836C0FC-B1FD-44FF-9643-AC0104419A80}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7836C0FC-B1FD-44FF-9643-AC0104419A80}.Release|Any CPU.Build.0 = Release|Any CPU {5D285685-62D1-4B1E-B469-18C1715471FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5D285685-62D1-4B1E-B469-18C1715471FF}.Release|Any CPU.ActiveCfg = Release|Any CPU {98A5BD88-7FCB-4295-B203-51E7FD77CE4F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -85,16 +73,6 @@ Global {CE492720-2000-4533-93AF-5AA71A65D305}.Debug|Any CPU.Build.0 = Debug|Any CPU {CE492720-2000-4533-93AF-5AA71A65D305}.Release|Any CPU.ActiveCfg = Release|Any CPU {CE492720-2000-4533-93AF-5AA71A65D305}.Release|Any CPU.Build.0 = Release|Any CPU - {BF11CF7F-0424-46F7-A60E-B614525C68C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BF11CF7F-0424-46F7-A60E-B614525C68C7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BF11CF7F-0424-46F7-A60E-B614525C68C7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BF11CF7F-0424-46F7-A60E-B614525C68C7}.Release|Any CPU.Build.0 = Release|Any CPU - {4C069416-CF7B-45C7-8C8F-B3D24DC16D01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4C069416-CF7B-45C7-8C8F-B3D24DC16D01}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8139DB48-8A96-405A-9B02-44C4AEF79FD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8139DB48-8A96-405A-9B02-44C4AEF79FD0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8139DB48-8A96-405A-9B02-44C4AEF79FD0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8139DB48-8A96-405A-9B02-44C4AEF79FD0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -104,15 +82,11 @@ Global {D1622176-4A8A-423B-9A74-8AD482659D01} = {3E35C7A6-722E-46FE-AFE0-2EFDF668DB44} {39375F75-D02B-453B-A1A5-D3D844EBA9FE} = {D2A273B8-0229-4121-8189-175960E7749D} {D5EC56A8-21AB-464D-BCA5-38F672560207} = {D2A273B8-0229-4121-8189-175960E7749D} - {7836C0FC-B1FD-44FF-9643-AC0104419A80} = {0574DFF6-39C8-43E6-8E91-92D03699BF35} {5D285685-62D1-4B1E-B469-18C1715471FF} = {D2A273B8-0229-4121-8189-175960E7749D} {98A5BD88-7FCB-4295-B203-51E7FD77CE4F} = {3E35C7A6-722E-46FE-AFE0-2EFDF668DB44} {64E80DBD-A61B-42A0-A0DB-4F36921EB83B} = {3E35C7A6-722E-46FE-AFE0-2EFDF668DB44} {13B74DC7-6A33-4F6D-879A-CB5F6FC5D73D} = {D2A273B8-0229-4121-8189-175960E7749D} {CE492720-2000-4533-93AF-5AA71A65D305} = {D2A273B8-0229-4121-8189-175960E7749D} - {BF11CF7F-0424-46F7-A60E-B614525C68C7} = {3E35C7A6-722E-46FE-AFE0-2EFDF668DB44} - {4C069416-CF7B-45C7-8C8F-B3D24DC16D01} = {D2A273B8-0229-4121-8189-175960E7749D} - {8139DB48-8A96-405A-9B02-44C4AEF79FD0} = {D2A273B8-0229-4121-8189-175960E7749D} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8A39B99E-1717-408D-9655-27AFFFB4798C} diff --git a/AutoMapper.OData.EFCore.Tests/AutoMapper.OData.EFCore.Tests.csproj b/AutoMapper.OData.EFCore.Tests/AutoMapper.OData.EFCore.Tests.csproj index 5c26fae..ac68450 100644 --- a/AutoMapper.OData.EFCore.Tests/AutoMapper.OData.EFCore.Tests.csproj +++ b/AutoMapper.OData.EFCore.Tests/AutoMapper.OData.EFCore.Tests.csproj @@ -7,13 +7,13 @@ - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/ExpressionBuilder.Tests/ExpressionBuilder.Tests.csproj b/ExpressionBuilder.Tests/ExpressionBuilder.Tests.csproj index b060ff2..63bed2d 100644 --- a/ExpressionBuilder.Tests/ExpressionBuilder.Tests.csproj +++ b/ExpressionBuilder.Tests/ExpressionBuilder.Tests.csproj @@ -7,12 +7,12 @@ - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/ExpressionBuilder.Tests/FilterTests.cs b/ExpressionBuilder.Tests/FilterTests.cs index 6304663..8c73d9f 100644 --- a/ExpressionBuilder.Tests/FilterTests.cs +++ b/ExpressionBuilder.Tests/FilterTests.cs @@ -2037,7 +2037,7 @@ public void NSCast_OnEnumerableEntityCollection_GeneratesExpression_WithOfTypeOn var filter = GetFilter("Category/EnumerableProducts/ExpressionBuilder.Tests.Data.DerivedProduct/any(p: p/ProductName eq 'ProductName')"); //assert - AssertFilterStringIsCorrect(filter, "$it => $it.Category.EnumerableProducts.OfType().Any(p => (p.ProductName == \"ProductName\"))"); + AssertFilterStringIsCorrect(filter, "$it => $it.Category.EnumerableProducts.Cast().Any(p => (p.ProductName == \"ProductName\"))"); } [Fact] @@ -2047,7 +2047,7 @@ public void NSCast_OnQueryableEntityCollection_GeneratesExpression_WithOfTypeOnQ var filter = GetFilter("Category/QueryableProducts/ExpressionBuilder.Tests.Data.DerivedProduct/any(p: p/ProductName eq 'ProductName')"); //assert - AssertFilterStringIsCorrect(filter, "$it => $it.Category.QueryableProducts.OfType().Any(p => (p.ProductName == \"ProductName\"))"); + AssertFilterStringIsCorrect(filter, "$it => $it.Category.QueryableProducts.Cast().Any(p => (p.ProductName == \"ProductName\"))"); } [Fact] @@ -2796,7 +2796,6 @@ public static List IsOfUnquotedComplexType new [] { "isof(null,ExpressionBuilder.Tests.Data.Address)", "ExpressionBuilder.Tests.Data.Address", "" }, new [] { "isof(null, ExpressionBuilder.Tests.Data.Address)", "ExpressionBuilder.Tests.Data.Address", "" }, new [] { "isof(null, ExpressionBuilder.Tests.Data.DerivedCategory)", "ExpressionBuilder.Tests.Data.DerivedCategory", "" }, - new [] { "isof(null, ExpressionBuilder.Tests.Data.DerivedCategory)", "ExpressionBuilder.Tests.Data.DerivedCategory", "" }, }; } } diff --git a/MigrationTool/MigrationContext.cs b/MigrationTool/MigrationContext.cs index 5ebd729..f650b19 100644 --- a/MigrationTool/MigrationContext.cs +++ b/MigrationTool/MigrationContext.cs @@ -10,7 +10,7 @@ public class MigrationContext : DbContext { protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { - optionsBuilder.UseSqlServer(@"Server=.\SQL2016;Database=YourDB;Trusted_Connection=True;"); + optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=WebApiEFCoreDatabase;ConnectRetryCount=0"); } public DbSet MandatorSet { get; set; } diff --git a/README.md b/README.md index 7cac700..4141e5a 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,7 @@ Creates LINQ expressions from ODataQueryOptions and executes the query. ## NuGet Package Downloads -[![NuGet](http://img.shields.io/nuget/v/AutoMapper.AspNetCore.OData.EFCore?label=AutoMapper.AspNetCore.OData.EFCore)](https://www.nuget.org/packages/AutoMapper.AspNetCore.OData.EFCore/) -[![NuGet](http://img.shields.io/nuget/v/AutoMapper.AspNetCore.OData.EF6?label=AutoMapper.AspNetCore.OData.EF6)](https://www.nuget.org/packages/AutoMapper.AspNetCore.OData.EF6/) -[![NuGet](http://img.shields.io/nuget/v/AutoMapper.AspNet.OData.EF6?label=AutoMapper.AspNet.OData.EF6)](https://www.nuget.org/packages/AutoMapper.AspNet.OData.EF6/) +[![NuGet](http://img.shields.io/nuget/v/AutoMapper.AspNetCore.OData.EFCore?label=AutoMapper.AspNetCore.OData.EFCore)](https://www.nuget.org/packages/AutoMapper.AspNetCore.OData.EFCore/) ## Usage To use: @@ -31,7 +29,6 @@ To use: ``` ```c# -public static async Task> GetAsync(this IQueryable query, IMapper mapper, ODataQueryOptions options, HandleNullPropagationOption handleNullPropagation = HandleNullPropagationOption.Default); public static async Task> GetQueryAsync(this IQueryable query, IMapper mapper, ODataQueryOptions options, HandleNullPropagationOption handleNullPropagation = HandleNullPropagationOption.Default); ``` diff --git a/SeedDatabase/appsettings.json b/SeedDatabase/appsettings.json index 275dbfc..154cd7c 100644 --- a/SeedDatabase/appsettings.json +++ b/SeedDatabase/appsettings.json @@ -1,5 +1,5 @@ { "ConnectionStrings": { - "DefaultConnection": "Server=.\\SQL2016;Database=YourDB;Trusted_Connection=True;" + "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=WebApiEFCoreDatabase;ConnectRetryCount=0" } } \ No newline at end of file diff --git a/Web.Tests/GetTests.cs b/Web.Tests/GetTests.cs index 2c60ef3..5e81c84 100644 --- a/Web.Tests/GetTests.cs +++ b/Web.Tests/GetTests.cs @@ -33,8 +33,7 @@ private void Initialize() [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void OpsTenantSearchAndFilterNoResult(string port) + public async Task OpsTenantSearchAndFilterNoResult(string port) { Test(await Get("/opstenant?$search=One&$filter=Name eq 'Two'", port)); @@ -46,8 +45,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void OpsTenantSearchAndFilterExpand(string port) + public async Task OpsTenantSearchAndFilterExpand(string port) { Test(await Get("/opstenant?$search=One&$filter=CreatedDate gt 2012-11-11T00:00:00.00Z&$expand=Buildings", port)); @@ -61,8 +59,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void OpsTenantSearchExpand(string port) + public async Task OpsTenantSearchExpand(string port) { Test(await Get("/opstenant?$search=One&$expand=Buildings", port)); @@ -76,8 +73,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void OpsTenantSearchNoExpand(string port) + public async Task OpsTenantSearchNoExpand(string port) { Test(await Get("/opstenant?$search=One", port)); @@ -91,8 +87,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void OpsTenantExpandBuildingsFilterEqAndOrderBy(string port) + public async Task OpsTenantExpandBuildingsFilterEqAndOrderBy(string port) { Test(await Get("/opstenant?$top=5&$expand=Buildings&$filter=Name eq 'One'&$orderby=Name desc", port)); @@ -106,8 +101,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void OpsTenantExpandBuildingsFilterNeAndOrderBy(string port) + public async Task OpsTenantExpandBuildingsFilterNeAndOrderBy(string port) { Test(await Get("/opstenant?$top=5&$expand=Buildings&$filter=Name ne 'One'&$orderby=Name desc", port)); @@ -121,8 +115,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void OpsTenantFilterEqNoExpand(string port) + public async Task OpsTenantFilterEqNoExpand(string port) { Test(await Get("/opstenant?$filter=Name eq 'One'", port)); @@ -136,8 +129,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void OpsTenantFilterGtDateNoExpand(string port) + public async Task OpsTenantFilterGtDateNoExpand(string port) { Test(await Get("/opstenant?$filter=CreatedDate gt 2012-11-11T00:00:00.00Z", port)); @@ -151,8 +143,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void OpsTenantFilterLtDateNoExpand(string port) + public async Task OpsTenantFilterLtDateNoExpand(string port) { Test(await Get("/opstenant?$filter=CreatedDate lt 2012-11-11T12:00:00.00Z", port)); @@ -164,8 +155,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void OpsTenantExpandBuildingsNoFilterAndOrderBy(string port) + public async Task OpsTenantExpandBuildingsNoFilterAndOrderBy(string port) { Test(await Get("/opstenant?$top=5&$expand=Buildings&$orderby=Name desc", port)); @@ -179,8 +169,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void OpsTenantNoExpandNoFilterAndOrderBy(string port) + public async Task OpsTenantNoExpandNoFilterAndOrderBy(string port) { Test(await Get("/opstenant?$orderby=Name desc", port)); @@ -194,8 +183,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void OpsTenantNoExpandFilterEqAndOrderBy(string port) + public async Task OpsTenantNoExpandFilterEqAndOrderBy(string port) { Test(await Get("/opstenant?$top=5&$filter=Name eq 'One'&$orderby=Name desc", port)); @@ -209,8 +197,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void OpsTenantExpandBuildingsSelectNameAndBuilderExpandBuilderExpandCityFilterNeAndOrderBy(string port) + public async Task OpsTenantExpandBuildingsSelectNameAndBuilderExpandBuilderExpandCityFilterNeAndOrderBy(string port) { Test(await Get("/opstenant?$top=5&$select=Name&$expand=Buildings($select=Name,Builder;$expand=Builder($select=Name,City;$expand=City))&$filter=Name ne 'One'&$orderby=Name desc", port)); @@ -227,8 +214,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void OpsTenantExpandBuildingsExpandBuilderExpandCityFilterNeAndOrderBy(string port) + public async Task OpsTenantExpandBuildingsExpandBuilderExpandCityFilterNeAndOrderBy(string port) { Test(await Get("/opstenant?$top=5&$expand=Buildings($expand=Builder($expand=City))&$filter=Name ne 'One'&$orderby=Name desc", port)); @@ -244,8 +230,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void BuildingExpandBuilderTenantFilterEqAndOrderBy(string port) + public async Task BuildingExpandBuilderTenantFilterEqAndOrderBy(string port) { Test(await Get("/corebuilding?$top=5&$expand=Builder,Tenant&$filter=name eq 'One L1'", port)); @@ -260,8 +245,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void BuildingExpandBuilderTenantFilterOnNestedPropertyAndOrderBy(string port) + public async Task BuildingExpandBuilderTenantFilterOnNestedPropertyAndOrderBy(string port) { Test(await Get("/corebuilding?$top=5&$expand=Builder,Tenant&$filter=Builder/Name eq 'Sam'&$orderby=Name asc", port)); @@ -276,8 +260,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void BuildingExpandBuilderTenantExpandCityFilterOnPropertyAndOrderBy(string port) + public async Task BuildingExpandBuilderTenantExpandCityFilterOnPropertyAndOrderBy(string port) { Test(await Get("/corebuilding?$top=5&$expand=Builder($expand=City),Tenant&$filter=Name ne 'One L2'&$orderby=Name desc", port)); @@ -291,8 +274,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void BuildingExpandBuilderTenantExpandCityFilterOnNestedNestedPropertyWithCount(string port) + public async Task BuildingExpandBuilderTenantExpandCityFilterOnNestedNestedPropertyWithCount(string port) { string query = "/corebuilding?$top=5&$expand=Builder($expand=City),Tenant&$filter=Builder/City/Name eq 'Leeds'&$count=true"; Test @@ -313,8 +295,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void BuildingExpandBuilderTenantExpandCityOrderByName(string port) + public async Task BuildingExpandBuilderTenantExpandCityOrderByName(string port) { Test(await Get("/corebuilding?$top=5&$expand=Builder($expand=City),Tenant&$orderby=Name desc", port)); @@ -327,8 +308,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void BuildingExpandBuilderTenantExpandCityOrderByNameThenByIdentity(string port) + public async Task BuildingExpandBuilderTenantExpandCityOrderByNameThenByIdentity(string port) { Test(await Get("/corebuilding?$top=5&$expand=Builder($expand=City),Tenant&$orderby=Name desc,Identity", port)); @@ -341,8 +321,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void BuildingExpandBuilderTenantExpandCityOrderByBuilderName(string port) + public async Task BuildingExpandBuilderTenantExpandCityOrderByBuilderName(string port) { Test(await Get("/corebuilding?$top=5&$expand=Builder($expand=City),Tenant&$orderby=Builder/Name", port)); @@ -356,8 +335,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void BuildingExpandBuilderTenantExpandCityOrderByBuilderNameSkip3Take1WithCount(string port) + public async Task BuildingExpandBuilderTenantExpandCityOrderByBuilderNameSkip3Take1WithCount(string port) { string query = "/corebuilding?$skip=4&$top=1&$expand=Builder($expand=City),Tenant&$orderby=Name desc,Identity&$count=true"; Test @@ -379,8 +357,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void BuildingExpandBuilderTenantExpandCityOrderByBuilderNameSkip3Take1NoCount(string port) + public async Task BuildingExpandBuilderTenantExpandCityOrderByBuilderNameSkip3Take1NoCount(string port) { string query = "/corebuilding?$skip=4&$top=1&$expand=Builder($expand=City),Tenant&$orderby=Name desc,Identity"; Test @@ -402,8 +379,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void BuildingSelectName_WithoutOrder_WithoutTop(string port) + public async Task BuildingSelectName_WithoutOrder_WithoutTop(string port) { Test(await Get("/corebuilding?$select=Name", port)); @@ -415,8 +391,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void OpsTenantOrderByCountOfReference(string port) + public async Task OpsTenantOrderByCountOfReference(string port) { Test(await Get("/opstenant?$expand=Buildings&$orderby=Buildings/$count desc", port)); @@ -432,8 +407,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void OpsTenantOrderByFilteredCount(string port) + public async Task OpsTenantOrderByFilteredCount(string port) { Test(await Get("/opstenant?$expand=Buildings&$orderby=Buildings/$count($filter=Name eq 'One L1') desc", port)); @@ -451,7 +425,7 @@ void Test(ICollection collection) [InlineData("16324")] //EF 6 seems to have a problem with circular reference Building/Tenant/Buildings //[InlineData("16325")] - public async void CoreBuildingOrderByCountOfChildReferenceOfReference(string port) + public async Task CoreBuildingOrderByCountOfChildReferenceOfReference(string port) { Test(await Get("/corebuilding?$expand=Tenant($expand=Buildings)&$orderby=Tenant/Buildings/$count desc", port)); void Test(ICollection collection) @@ -465,8 +439,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void CoreBuildingOrderByPropertyOfChildReferenceOfReference(string port) + public async Task CoreBuildingOrderByPropertyOfChildReferenceOfReference(string port) { Test(await Get("/corebuilding?$expand=Builder($expand=City)&$orderby=Builder/City/Name desc", port)); void Test(ICollection collection) @@ -480,8 +453,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void OpsTenantSelectNameExpandBuildings(string port) + public async Task OpsTenantSelectNameExpandBuildings(string port) { Test(await Get("/opstenant?$select=Name&$expand=Buildings&$orderby=Name", port)); @@ -496,8 +468,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void OpsTenantExpandBuildingsFilterEqAndOrderBy_FirstBuildingHasValues(string port) + public async Task OpsTenantExpandBuildingsFilterEqAndOrderBy_FirstBuildingHasValues(string port) { Test(await Get("/opstenant?$top=5&$select=Buildings&$expand=Buildings&$filter=Name eq 'One'&$orderby=Name desc", port)); @@ -514,8 +485,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void BuildingSelectNameExpandBuilder_BuilderNameShouldBeSam(string port) + public async Task BuildingSelectNameExpandBuilder_BuilderNameShouldBeSam(string port) { Test(await Get("/corebuilding?$top=5&$select=Name&$expand=Builder($select=Name)&$filter=name eq 'One L1'", port)); @@ -532,8 +502,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void BuildingExpandBuilderSelectNamefilterEqAndOrderBy(string port) + public async Task BuildingExpandBuilderSelectNamefilterEqAndOrderBy(string port) { Test(await Get("/corebuilding?$top=5&$expand=Builder($select=Name)&$filter=name eq 'One L1'", port)); @@ -550,8 +519,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void BuildingExpandBuilderSelectNameExpandCityFilterEqAndOrderBy_CityShouldBeExpanded_BuilderNameShouldBeSam_BuilderIdShouldBeZero(string port) + public async Task BuildingExpandBuilderSelectNameExpandCityFilterEqAndOrderBy_CityShouldBeExpanded_BuilderNameShouldBeSam_BuilderIdShouldBeZero(string port) { Test(await Get("/corebuilding?$top=5&$expand=Builder($select=Name;$expand=City)&$filter=name eq 'One L1'", port)); @@ -569,8 +537,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void OpsTenantExpandBuildingsSelectNameAndBuilderExpandBuilderExpandCityFilterNeAndOrderBy_filterAndSortChildCollection(string port) + public async Task OpsTenantExpandBuildingsSelectNameAndBuilderExpandBuilderExpandCityFilterNeAndOrderBy_filterAndSortChildCollection(string port) { Test(await Get("/opstenant?$top=5&$select=Name&$expand=Buildings($filter=Name ne 'Two L1';$orderby=Name;$select=Name,Builder;$expand=Builder($select=Name,City;$expand=City))&$filter=Name ne 'One'&$orderby=Name desc", port)); @@ -588,8 +555,7 @@ void Test(ICollection collection) [Theory] [InlineData("16324")] - [InlineData("16325")] - public async void OpsTenantExpandBuildingsExpandBuilderExpandCityFilterNeAndOrderBy_filterAndSortChildCollection(string port) + public async Task OpsTenantExpandBuildingsExpandBuilderExpandCityFilterNeAndOrderBy_filterAndSortChildCollection(string port) { Test(await Get("/opstenant?$top=5&$expand=Buildings($filter=Name ne '';$orderby=Name desc;$expand=Builder($expand=City))&$filter=Name ne 'One'&$orderby=Name desc", port)); diff --git a/Web.Tests/Web.Tests.csproj b/Web.Tests/Web.Tests.csproj index b8b2ebe..e7dc576 100644 --- a/Web.Tests/Web.Tests.csproj +++ b/Web.Tests/Web.Tests.csproj @@ -9,13 +9,13 @@ - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/WebAPI.OData.EFCore/WebAPI.OData.EFCore.csproj b/WebAPI.OData.EFCore/WebAPI.OData.EFCore.csproj index 314e498..0812253 100644 --- a/WebAPI.OData.EFCore/WebAPI.OData.EFCore.csproj +++ b/WebAPI.OData.EFCore/WebAPI.OData.EFCore.csproj @@ -5,9 +5,8 @@ - - - + + diff --git a/WebAPI.OData.EFCore/appsettings.json b/WebAPI.OData.EFCore/appsettings.json index dc91c7b..55de503 100644 --- a/WebAPI.OData.EFCore/appsettings.json +++ b/WebAPI.OData.EFCore/appsettings.json @@ -1,6 +1,6 @@ { "ConnectionStrings": { - "DefaultConnection": "Server=.\\SQL2016;Database=YourDB;Trusted_Connection=True;TrustServerCertificate=True;" + "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=WebApiEFCoreDatabase;ConnectRetryCount=0" }, "Logging": { "LogLevel": {