因为您已经指定了 EnableQuery 属性,所以您可以使用 $apply 对不同的字段进行分组,而无需添加任何自定义函数或参数,您可以立即免费获得此功能:
GET /odata/Products?$apply=groupby((foo))&top=10&$count=true
这是简单的 OData v4 标准语法,不需要任何代码修改即可实现。不要更改您想要支持不同查询的每个控制器,您无法提前 100% 知道您的客户端应用程序可能希望在哪些控制器上使用此功能,因此请在开始自定义之前使用提供的功能。
当然,这种方法有一个注意事项,它不能在 100% 的时间内实现:
- $filter 和 $orderby 只能对 group by 子句中指定的字段进行操作
这可能需要您在分组语句中包含其他字段,并且对于某些复杂的过滤结果数据集可能不令人满意,在这种情况下,我们发现更容易支持通过 HTTP 标头传递额外的预过滤参数,可以在应用传入的查询选项之前应用于查询,请注意,这只是必要的,因为我们的过滤条件与租赁和安全相关,因此如果您忽略安全描述符,结果数据集会有更多重复条目。
只是为了好玩,这里是我们自定义的 GET 函数,如果它被传入,它会应用预过滤器:
[EnableQuery]
public IQueryable<FooBarBaz> Get(ODataQueryOptions<FooBarBaz> queryOptions, bool distinct)
{
DbQuery<FooBarBaz> query = Repository;
query = this.ApplyUserPolicy(query);
return Ok(query);
}
以下是在基类中实现的,因此我们在每个控制器中都没有它:
/// <summary>
/// Apply default user policy to the DBQuery that will be used by actions on this controller.
/// The big one we support here is X-Filter HTTP headers, so now you can provide top level filtering in the header of the request
/// before the normal OData filter and query parameters are applied.
/// This is useful when you want to use $apply and $filter together but on separate sets of conditions.
/// </summary>
/// <param name="dataTable">DBQuery to apply the policy to</param>
/// <returns>Returns IQueryable entity query ready for processing with the headers applied (if any)</returns>
private IQueryable<TEntity> ApplyUserPolicy(DbQuery<TEntity> dataTable)
{
// Proprietary Implementation of Security Tokens
//var tokenData = SystemController.CurrentToken(Request);
//IQueryable<TEntity> query = ApplyUserPolicy(dataTable, tokenData);
IQueryable<TEntity> query = dataTable.AsQueryable();
// Now try and apply an OData filter passed in as a header.
// This means we are applying a global filter BEFORE the normal OData query params
// ... we can filter before $apply and group by
System.Collections.Generic.IEnumerable<string> filters = null;
if (Request.Headers.TryGetValues("X-Filter", out filters))
{
foreach (var filter in filters)
{
//var expressions = filter.Split(',');
//foreach (var expression in expressions)
{
var expression = filter;
Dictionary<string, string> options = new Dictionary<string, string>()
{
{ "$filter" , expression },
};
var model = this.Request.ODataProperties().Model;
IEdmNavigationSource source = model.FindDeclaredEntitySet(this.GetEntitySetName());
var type = source.EntityType();
Microsoft.OData.Core.UriParser.ODataQueryOptionParser parser
= new Microsoft.OData.Core.UriParser.ODataQueryOptionParser(model, type, source, options);
var filterClause = parser.ParseFilter(); // parse $filter
FilterQueryOption option = new FilterQueryOption(expression, new ODataQueryContext(model, typeof(TEntity), this.Request.ODataProperties().Path), parser);
query = (IQueryable<TEntity>)option.ApplyTo(query, new ODataQuerySettings());
}
}
}
return query;
}
如果不出意外,尝试将 AdaptiveLINQ 出售给您的经理会更便宜:)