EnableQuery 属性を指定したため、$apply を使用して個別のフィールドをグループ化できます。カスタム関数やパラメーターを追加する必要はありません。これをすぐに無料で入手できます。
GET /odata/Products?$apply=groupby((foo))&top=10&$count=true
これは単純な OData v4 標準構文であり、実装するためにコードを変更する必要はありません。個別のクエリをサポートする各コントローラーを変更しないでください。クライアント アプリがこの機能を必要とするコントローラーを 100% 事前に知ることはできないため、カスタマイズを開始する前に提供されている機能を使用してください。
もちろん、このアプローチには 100% 実行可能ではないという警告があります。
- $filter と $orderby は、group by 句で指定されたフィールドに対してのみ操作できます
これには、グループ化ステートメントに追加のフィールドを含める必要がある場合があり、一部の複雑なフィルタリングでは、結果のデータセットが満足のいくものではない場合があります。渡されたクエリ オプションが適用される前にクエリに適用されますが、これが必要だったのは、フィルタ条件がテナンシーとセキュリティに関連していたためであり、セキュリティ記述子を無視した場合、結果のデータ セットにはさらに多くの重複エントリが含まれていたためであることに注意してください。
ちょっとした楽しみとして、プレフィルターが渡された場合にそれを適用するカスタム 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 をマネージャーに販売しようとする方が安上がりです :)