diff --git a/AutoMapper.AspNetCore.OData.EFCore/LinqExtensions.cs b/AutoMapper.AspNetCore.OData.EFCore/LinqExtensions.cs index cb6178b..ebebdda 100644 --- a/AutoMapper.AspNetCore.OData.EFCore/LinqExtensions.cs +++ b/AutoMapper.AspNetCore.OData.EFCore/LinqExtensions.cs @@ -133,7 +133,8 @@ public static Expression GetOrderByMethod(this Expression expression, options.OrderBy?.OrderByClause, typeof(T), options.Skip?.Value, - GetPageSize() + GetPageSize(), + options.Count?.Value ); int? GetPageSize() @@ -153,12 +154,12 @@ public static Expression GetOrderByMethod(this Expression expression, } public static Expression GetQueryableMethod(this Expression expression, - ODataQueryContext context, OrderByClause orderByClause, Type type, int? skip, int? top) + ODataQueryContext context, OrderByClause orderByClause, Type type, int? skip, int? top, bool? count) { - if (orderByClause is null && skip is null && top is null) + if (orderByClause is null && skip is null && top is null && count is null) return null; - if (orderByClause is null && (skip is not null || top is not null)) + if (orderByClause is null && (skip is not null || top is not null || count is not null)) { var orderBySettings = context.FindSortableProperties(type); @@ -168,13 +169,15 @@ public static Expression GetQueryableMethod(this Expression expression, return expression .GetDefaultOrderByCall(orderBySettings) .GetSkipCall(skip) - .GetTakeCall(top); + .GetTakeCall(top) + .GetCountCall(count); } return expression .GetOrderByCall(orderByClause, context) .GetSkipCall(skip) - .GetTakeCall(top); + .GetTakeCall(top) + .GetCountCall(count); } private static bool NoQueryableMethod(ODataQueryOptions options, ODataSettings oDataSettings) @@ -333,6 +336,20 @@ public static List GetReferencePath(this List list, SingleResour return list; } } + + public static Expression GetCountCall(this Expression expression, CountQueryOption count) + { + if (count == null) return expression; + + return expression.GetCountCall(count.Value); + } + + public static Expression GetCountCall(this Expression expression, bool? count) + { + if (count == null) return expression; + + return expression.GetCountCall(); + } public static Expression GetSkipCall(this Expression expression, SkipQueryOption skip) { @@ -560,14 +577,14 @@ FilterOptions GetFilter() QueryOptions GetQuery() => HasQuery() - ? new QueryOptions(next.OrderByOption, (int?)next.SkipOption, (int?)next.TopOption) + ? new QueryOptions(next.OrderByOption, (int?)next.SkipOption, (int?)next.TopOption, next.CountOption) : null; bool HasFilter() => memberType.IsList() && next.FilterOption != null; bool HasQuery() - => memberType.IsList() && (next.OrderByOption != null || next.SkipOption.HasValue || next.TopOption.HasValue); + => memberType.IsList() && (next.OrderByOption != null || next.SkipOption.HasValue || next.TopOption.HasValue || next.CountOption.HasValue); }); } @@ -731,7 +748,7 @@ List> GetQueryMethods() MemberName = next.MemberName, MemberType = next.MemberType, ParentType = next.ParentType, - QueryOptions = new QueryOptions(next.QueryOptions.OrderByClause, next.QueryOptions.Skip, next.QueryOptions.Top) + QueryOptions = new QueryOptions(next.QueryOptions.OrderByClause, next.QueryOptions.Skip, next.QueryOptions.Top, next.QueryOptions.Count) } );//add expansion with query options @@ -759,13 +776,15 @@ public class ODataExpansionOptions : Expansion public class QueryOptions { - public QueryOptions(OrderByClause orderByClause, int? skip, int? top) + public QueryOptions(OrderByClause orderByClause, int? skip, int? top, bool? count) { OrderByClause = orderByClause; Skip = skip; Top = top; + Count = count; } + public bool? Count { get; set; } public OrderByClause OrderByClause { get; set; } public int? Skip { get; set; } public int? Top { get; set; } diff --git a/AutoMapper.AspNetCore.OData.EFCore/Visitors/MethodAppender.cs b/AutoMapper.AspNetCore.OData.EFCore/Visitors/MethodAppender.cs index 6498000..9753dd1 100644 --- a/AutoMapper.AspNetCore.OData.EFCore/Visitors/MethodAppender.cs +++ b/AutoMapper.AspNetCore.OData.EFCore/Visitors/MethodAppender.cs @@ -35,7 +35,8 @@ protected override Expression VisitMethodCall(MethodCallExpression node) expansion.QueryOptions.OrderByClause, elementType, expansion.QueryOptions.Skip, - expansion.QueryOptions.Top + expansion.QueryOptions.Top, + expansion.QueryOptions.Count ); } diff --git a/AutoMapper.OData.EFCore.Tests/GetQueryTests.cs b/AutoMapper.OData.EFCore.Tests/GetQueryTests.cs index 5c9059b..ce89d30 100644 --- a/AutoMapper.OData.EFCore.Tests/GetQueryTests.cs +++ b/AutoMapper.OData.EFCore.Tests/GetQueryTests.cs @@ -963,6 +963,25 @@ static void Test(ICollection collection) } } + [Fact] + public async void CountingOnChildCollection() + { + string query = "/CategoryModel?$expand=Products($count=true)"; + Test + ( + Get + ( + query, + GetCategories() + ) + ); + + static void Test(ICollection collection) + { + // TODO: Assert count value is equal to 2 + } + } + [Fact] public async void FilteringOnRoot_AndChildCollection_WithNoMatches() {