Skip to content

Commit 1c7c66e

Browse files
authored
Merge pull request #83 from darjanbogdan/feature/expand-query-settings
Expand ODataSettings with additional properties to enable more configuration
2 parents 6224f58 + caf1090 commit 1c7c66e

File tree

10 files changed

+560
-35
lines changed

10 files changed

+560
-35
lines changed

AutoMapper.AspNet.OData.EF6/ODataQueryOptionsExtensions.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,18 @@ public static void AddCountOptionsResult<TModel, TData>(this ODataQueryOptions<T
3030

3131
options.Request.ODataProperties().TotalCount = longCount;
3232
}
33+
34+
/// <summary>Adds the next link options to the result.</summary>
35+
/// <typeparam name="TModel">The type of the model.</typeparam>
36+
/// <param name="options">The odata options.</param>
37+
/// <param name="pageSize">The page size.</param>
38+
/// <autogeneratedoc />
39+
public static void AddNextLinkOptionsResult<TModel>(this ODataQueryOptions<TModel> options, int pageSize)
40+
{
41+
if (options.Request == null)
42+
return;
43+
44+
options.Request.ODataProperties().NextLink = options.Request.GetNextPageLink(pageSize);
45+
}
3346
}
3447
}

AutoMapper.AspNetCore.OData.EF6/QueryableExtensions.cs

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public static class QueryableExtensions
2323
/// <param name="options"></param>
2424
/// <param name="handleNullPropagation"></param>
2525
/// <returns></returns>
26+
[Obsolete("\"Use ICollection<TModel> Get<TModel, TData>(this IQueryable<TData> query, IMapper mapper, ODataQueryOptions<TModel> options, QuerySettings querySettings)\"")]
2627
public static ICollection<TModel> Get<TModel, TData>(this IQueryable<TData> query, IMapper mapper, ODataQueryOptions<TModel> options, HandleNullPropagationOption handleNullPropagation = HandleNullPropagationOption.Default)
2728
where TModel : class
2829
=> Task.Run(async () => await query.GetAsync(mapper, options, handleNullPropagation)).Result;
@@ -39,8 +40,7 @@ public static ICollection<TModel> Get<TModel, TData>(this IQueryable<TData> quer
3940
/// <returns></returns>
4041
public static ICollection<TModel> Get<TModel, TData>(this IQueryable<TData> query, IMapper mapper, ODataQueryOptions<TModel> options, QuerySettings querySettings)
4142
where TModel : class
42-
=> query.Get(mapper, options, querySettings?.ODataSettings?.HandleNullPropagation ?? HandleNullPropagationOption.Default);
43-
43+
=> Task.Run(async () => await query.GetAsync(mapper, options, querySettings)).Result;
4444

4545
/// <summary>
4646
/// GetAsync
@@ -50,28 +50,42 @@ public static ICollection<TModel> Get<TModel, TData>(this IQueryable<TData> quer
5050
/// <param name="query"></param>
5151
/// <param name="mapper"></param>
5252
/// <param name="options"></param>
53-
/// <param name="handleNullPropagation"></param>
53+
/// <param name="querySettings"></param>
5454
/// <returns></returns>
55-
public static async Task<ICollection<TModel>> GetAsync<TModel, TData>(this IQueryable<TData> query, IMapper mapper, ODataQueryOptions<TModel> options, HandleNullPropagationOption handleNullPropagation = HandleNullPropagationOption.Default)
55+
public static async Task<ICollection<TModel>> GetAsync<TModel, TData>(this IQueryable<TData> query, IMapper mapper, ODataQueryOptions<TModel> options, QuerySettings querySettings = null)
5656
where TModel : class
5757
{
5858
List<Expression<Func<TModel, object>>> includeExpressions = options.SelectExpand.GetIncludes().BuildIncludes<TModel>().ToList();
59-
Expression<Func<TModel, bool>> filter = options.Filter.ToFilterExpression<TModel>(handleNullPropagation);
60-
Expression<Func<IQueryable<TModel>, IQueryable<TModel>>> queryableExpression = options.GetQueryableExpression();
59+
Expression<Func<TModel, bool>> filter = options.Filter.ToFilterExpression<TModel>(querySettings?.ODataSettings?.HandleNullPropagation ?? HandleNullPropagationOption.Default);
60+
Expression<Func<IQueryable<TModel>, IQueryable<TModel>>> queryableExpression = options.GetQueryableExpression(querySettings?.ODataSettings);
6161
Expression<Func<IQueryable<TModel>, long>> countExpression = LinqExtensions.GetCountExpression<TModel>(filter);
6262

6363
options.AddExpandOptionsResult();
6464
if (options.Count?.Value == true)
6565
options.AddCountOptionsResult<TModel, TData>(await query.QueryAsync(mapper, countExpression));
6666

67+
if (querySettings?.ODataSettings?.PageSize.HasValue == true)
68+
options.AddNextLinkOptionsResult(querySettings.ODataSettings.PageSize.Value);
69+
6770
ICollection<TModel> collection = await query.GetAsync(mapper, filter, queryableExpression, includeExpressions);
6871

6972
return collection;
7073
}
7174

72-
public static async Task<ICollection<TModel>> GetAsync<TModel, TData>(this IQueryable<TData> query, IMapper mapper, ODataQueryOptions<TModel> options, QuerySettings querySettings = null)
75+
/// <summary>
76+
/// GetAsync
77+
/// </summary>
78+
/// <typeparam name="TModel"></typeparam>
79+
/// <typeparam name="TData"></typeparam>
80+
/// <param name="query"></param>
81+
/// <param name="mapper"></param>
82+
/// <param name="options"></param>
83+
/// <param name="handleNullPropagation"></param>
84+
/// <returns></returns>
85+
[Obsolete("\"Use Task<ICollection<TModel>> GetAsync<TModel, TData>(this IQueryable<TData> query, IMapper mapper, ODataQueryOptions<TModel> options, QuerySettings querySettings = null)\"")]
86+
public static async Task<ICollection<TModel>> GetAsync<TModel, TData>(this IQueryable<TData> query, IMapper mapper, ODataQueryOptions<TModel> options, HandleNullPropagationOption handleNullPropagation = HandleNullPropagationOption.Default)
7387
where TModel : class
74-
=> await query.GetAsync(mapper, options, querySettings?.ODataSettings?.HandleNullPropagation ?? HandleNullPropagationOption.Default);
88+
=> await query.GetAsync(mapper, options, new QuerySettings { ODataSettings = new ODataSettings { HandleNullPropagation = handleNullPropagation } });
7589

7690
/// <summary>
7791
/// GetQueryAsync
@@ -83,6 +97,7 @@ public static async Task<ICollection<TModel>> GetAsync<TModel, TData>(this IQuer
8397
/// <param name="options"></param>
8498
/// <param name="handleNullPropagation"></param>
8599
/// <returns></returns>
100+
[Obsolete("\"Use Task<IQueryable<TModel>> GetQueryAsync<TModel, TData>(this IQueryable<TData> query, IMapper mapper, ODataQueryOptions<TModel> options, QuerySettings querySettings = null)\"")]
86101
public static async Task<IQueryable<TModel>> GetQueryAsync<TModel, TData>(this IQueryable<TData> query, IMapper mapper, ODataQueryOptions<TModel> options, HandleNullPropagationOption handleNullPropagation = HandleNullPropagationOption.Default)
87102
where TModel : class
88103
=> await query.GetQueryAsync(mapper, options, new QuerySettings { ODataSettings = new ODataSettings { HandleNullPropagation = handleNullPropagation } });
@@ -108,13 +123,16 @@ public static async Task<IQueryable<TModel>> GetQueryAsync<TModel, TData>(this I
108123
.ToList();
109124

110125
Expression<Func<TModel, bool>> filter = options.Filter.ToFilterExpression<TModel>(querySettings?.ODataSettings?.HandleNullPropagation ?? HandleNullPropagationOption.Default);
111-
Expression<Func<IQueryable<TModel>, IQueryable<TModel>>> queryableExpression = options.GetQueryableExpression();
126+
Expression<Func<IQueryable<TModel>, IQueryable<TModel>>> queryableExpression = options.GetQueryableExpression(querySettings?.ODataSettings);
112127
Expression<Func<IQueryable<TModel>, long>> countExpression = LinqExtensions.GetCountExpression<TModel>(filter);
113128

114129
options.AddExpandOptionsResult();
115130
if (options.Count?.Value == true)
116131
options.AddCountOptionsResult<TModel, TData>(await query.QueryAsync(mapper, countExpression));
117132

133+
if (querySettings?.ODataSettings?.PageSize.HasValue == true)
134+
options.AddNextLinkOptionsResult(querySettings.ODataSettings.PageSize.Value);
135+
118136
IQueryable<TModel> queryable = await query.GetQueryAsync(mapper, filter, queryableExpression, includeExpressions, querySettings?.ProjectionSettings);
119137

120138
return queryable.UpdateQueryableExpression(expansions);

AutoMapper.AspNetCore.OData.EFCore/LinqExtensions.cs

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,38 +57,57 @@ private static Expression GetLongCountMethod(ParameterExpression param, Expressi
5757
/// </summary>
5858
/// <typeparam name="T"></typeparam>
5959
/// <param name="options"></param>
60+
/// <param name="oDataSettings"></param>
6061
/// <returns></returns>
61-
public static Expression<Func<IQueryable<T>, IQueryable<T>>> GetQueryableExpression<T>(this ODataQueryOptions<T> options)
62+
public static Expression<Func<IQueryable<T>, IQueryable<T>>> GetQueryableExpression<T>(this ODataQueryOptions<T> options, ODataSettings oDataSettings = null)
6263
{
63-
if (options.OrderBy == null && options.Top == null)
64+
if (NoQueryableMethod(options, oDataSettings))
6465
return null;
6566

6667
ParameterExpression param = Expression.Parameter(typeof(IQueryable<T>), "q");
6768

6869
return Expression.Lambda<Func<IQueryable<T>, IQueryable<T>>>
6970
(
70-
param.GetOrderByMethod(options), param
71+
param.GetOrderByMethod(options, oDataSettings), param
7172
);
7273
}
7374

74-
[Obsolete("Use \"public static Expression GetOrderByMethod<T>(this Expression expression, ODataQueryOptions<T> options)\" instead.")]
75+
[Obsolete("Use \"Expression GetOrderByMethod<T>(this Expression expression, ODataQueryOptions<T> options, ODataSettings oDataSettings = null)\" instead.")]
7576
public static Expression GetOrderByMethod<T>(this ODataQueryOptions<T> options, Expression expression)
7677
=> expression.GetOrderByMethod<T>(options);
7778

78-
public static Expression GetOrderByMethod<T>(this Expression expression, ODataQueryOptions<T> options)
79+
public static Expression GetOrderByMethod<T>(this Expression expression, ODataQueryOptions<T> options, ODataSettings oDataSettings = null)
7980
{
80-
if (options.OrderBy == null && options.Top == null)
81+
if (NoQueryableMethod(options, oDataSettings))
8182
return null;
8283

8384
return expression.GetQueryableMethod
8485
(
8586
options.OrderBy?.OrderByClause,
8687
typeof(T),
8788
options.Skip?.Value,
88-
options.Top?.Value
89+
GetPageSize()
8990
);
91+
92+
int? GetPageSize()
93+
{
94+
if (oDataSettings?.PageSize == null && options.Top == null)
95+
return null;
96+
97+
if (options.Top == null)
98+
return oDataSettings.PageSize;
99+
else if (oDataSettings?.PageSize == null)
100+
return options.Top.Value;
101+
102+
return options.Top.Value < oDataSettings.PageSize
103+
? options.Top.Value
104+
: oDataSettings.PageSize;
105+
}
90106
}
91107

108+
private static bool NoQueryableMethod(ODataQueryOptions options, ODataSettings oDataSettings)
109+
=> options.OrderBy == null && options.Top == null && oDataSettings?.PageSize == null;
110+
92111
public static Expression GetQueryableMethod(this Expression expression, OrderByClause orderByClause, Type type, int? skip, int? top)
93112
{
94113
if (orderByClause == null && !top.HasValue)

AutoMapper.AspNetCore.OData.EFCore/ODataQueryOptionsExtensions.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,18 @@ public static void AddCountOptionsResult<TModel, TData>(this ODataQueryOptions<T
3333

3434
options.Request.ODataFeature().TotalCount = longCount;
3535
}
36+
37+
/// <summary>Adds the next link options to the result.</summary>
38+
/// <typeparam name="TModel">The type of the model.</typeparam>
39+
/// <param name="options">The odata options.</param>
40+
/// <param name="pageSize">The page size.</param>
41+
/// <autogeneratedoc />
42+
public static void AddNextLinkOptionsResult<TModel>(this ODataQueryOptions<TModel> options, int pageSize)
43+
{
44+
if (options.Request == null)
45+
return;
46+
47+
options.Request.ODataFeature().NextLink = options.Request.GetNextPageLink(pageSize);
48+
}
3649
}
3750
}

AutoMapper.AspNetCore.OData.EFCore/ODataSettings.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,13 @@ public class ODataSettings
1515
/// The default is <see cref="F:Microsoft.AspNet.OData.Query.HandleNullPropagationOption.Default" />.
1616
/// </value>
1717
public HandleNullPropagationOption HandleNullPropagation { get; set; } = HandleNullPropagationOption.Default;
18+
19+
/// <summary>
20+
/// Gets or sets the maximum number of query results to return.
21+
/// </summary>
22+
/// <value>
23+
/// The maximum number of query results to return, or null if there is no limit. Default is null.
24+
/// </value>
25+
public int? PageSize { get; set; }
1826
}
1927
}

AutoMapper.AspNetCore.OData.EFCore/QueryableExtensions.cs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,33 +14,39 @@ namespace AutoMapper.AspNet.OData
1414
{
1515
public static class QueryableExtensions
1616
{
17+
[Obsolete("\"Use ICollection<TModel> Get<TModel, TData>(this IQueryable<TData> query, IMapper mapper, ODataQueryOptions<TModel> options, QuerySettings querySettings = null)\"")]
1718
public static ICollection<TModel> Get<TModel, TData>(this IQueryable<TData> query, IMapper mapper, ODataQueryOptions<TModel> options, HandleNullPropagationOption handleNullPropagation = HandleNullPropagationOption.False)
1819
where TModel : class
1920
=> Task.Run(async () => await query.GetAsync(mapper, options, handleNullPropagation)).Result;
2021

2122
public static ICollection<TModel> Get<TModel, TData>(this IQueryable<TData> query, IMapper mapper, ODataQueryOptions<TModel> options, QuerySettings querySettings = null)
2223
where TModel : class
23-
=> query.Get(mapper, options, querySettings?.ODataSettings?.HandleNullPropagation ?? HandleNullPropagationOption.False);
24+
=> Task.Run(async () => await query.GetAsync(mapper, options, querySettings)).Result;
2425

25-
public static async Task<ICollection<TModel>> GetAsync<TModel, TData>(this IQueryable<TData> query, IMapper mapper, ODataQueryOptions<TModel> options, HandleNullPropagationOption handleNullPropagation = HandleNullPropagationOption.False)
26+
public static async Task<ICollection<TModel>> GetAsync<TModel, TData>(this IQueryable<TData> query, IMapper mapper, ODataQueryOptions<TModel> options, QuerySettings querySettings = null)
2627
where TModel : class
2728
{
2829
ICollection<Expression<Func<IQueryable<TModel>, IIncludableQueryable<TModel, object>>>> includeExpressions = options.SelectExpand.GetIncludes().BuildIncludesExpressionCollection<TModel>()?.ToList();
29-
Expression<Func<TModel, bool>> filter = options.Filter.ToFilterExpression<TModel>(handleNullPropagation);
30-
Expression<Func<IQueryable<TModel>, IQueryable<TModel>>> queryableExpression = options.GetQueryableExpression();
30+
Expression<Func<TModel, bool>> filter = options.Filter.ToFilterExpression<TModel>(querySettings?.ODataSettings?.HandleNullPropagation ?? HandleNullPropagationOption.False);
31+
Expression<Func<IQueryable<TModel>, IQueryable<TModel>>> queryableExpression = options.GetQueryableExpression(querySettings?.ODataSettings);
3132
Expression<Func<IQueryable<TModel>, long>> countExpression = LinqExtensions.GetCountExpression<TModel>(filter);
3233

3334
options.AddExpandOptionsResult();
3435
if (options.Count?.Value == true)
3536
options.AddCountOptionsResult<TModel, TData>(await query.QueryAsync(mapper, countExpression));
3637

38+
if (querySettings?.ODataSettings?.PageSize.HasValue == true)
39+
options.AddNextLinkOptionsResult(querySettings.ODataSettings.PageSize.Value);
40+
3741
return await query.GetAsync(mapper, filter, queryableExpression, includeExpressions);
3842
}
3943

40-
public static async Task<ICollection<TModel>> GetAsync<TModel, TData>(this IQueryable<TData> query, IMapper mapper, ODataQueryOptions<TModel> options, QuerySettings querySettings = null)
44+
[Obsolete("\"Use Task<ICollection<TModel>> GetAsync<TModel, TData>(this IQueryable<TData> query, IMapper mapper, ODataQueryOptions<TModel> options, QuerySettings querySettings = null)\"")]
45+
public static async Task<ICollection<TModel>> GetAsync<TModel, TData>(this IQueryable<TData> query, IMapper mapper, ODataQueryOptions<TModel> options, HandleNullPropagationOption handleNullPropagation = HandleNullPropagationOption.False)
4146
where TModel : class
42-
=> await query.GetAsync(mapper, options, querySettings?.ODataSettings?.HandleNullPropagation ?? HandleNullPropagationOption.False);
47+
=> await query.GetAsync(mapper, options, new QuerySettings { ODataSettings = new ODataSettings { HandleNullPropagation = handleNullPropagation } });
4348

49+
[Obsolete("\"Use Task<IQueryable<TModel>> GetQueryAsync<TModel, TData>(this IQueryable<TData> query, IMapper mapper, ODataQueryOptions<TModel> options, QuerySettings querySettings = null)\"")]
4450
public static async Task<IQueryable<TModel>> GetQueryAsync<TModel, TData>(this IQueryable<TData> query, IMapper mapper, ODataQueryOptions<TModel> options, HandleNullPropagationOption handleNullPropagation = HandleNullPropagationOption.False)
4551
where TModel : class
4652
=> await query.GetQueryAsync(mapper, options, new QuerySettings { ODataSettings = new ODataSettings { HandleNullPropagation = handleNullPropagation } });
@@ -56,13 +62,16 @@ public static async Task<IQueryable<TModel>> GetQueryAsync<TModel, TData>(this I
5662
.ToList();
5763

5864
Expression<Func<TModel, bool>> filter = options.Filter.ToFilterExpression<TModel>(querySettings?.ODataSettings?.HandleNullPropagation ?? HandleNullPropagationOption.False);
59-
Expression<Func<IQueryable<TModel>, IQueryable<TModel>>> queryableExpression = options.GetQueryableExpression();
65+
Expression<Func<IQueryable<TModel>, IQueryable<TModel>>> queryableExpression = options.GetQueryableExpression(querySettings?.ODataSettings);
6066
Expression<Func<IQueryable<TModel>, long>> countExpression = LinqExtensions.GetCountExpression<TModel>(filter);
6167

6268
options.AddExpandOptionsResult();
6369
if (options.Count?.Value == true)
6470
options.AddCountOptionsResult<TModel, TData>(await query.QueryAsync(mapper, countExpression));
6571

72+
if (querySettings?.ODataSettings?.PageSize.HasValue == true)
73+
options.AddNextLinkOptionsResult(querySettings.ODataSettings.PageSize.Value);
74+
6675
IQueryable<TModel> queryable = await query.GetQueryAsync(mapper, filter, queryableExpression, includeExpressions, querySettings?.ProjectionSettings);
6776

6877
return queryable.UpdateQueryableExpression(expansions);

0 commit comments

Comments
 (0)