1

在我的 ODATA-v4 控制器中,我有以下代码:

var fn = reportModelBuilder.EntityType<CurrentTestResult>()
         .Collection.Function("Breakdown").Returns<int>();

在 CurrentTestResultController.cs 中,我看似简单:

[EnableQuery(AllowedQueryOptions = AllowedQueryOptions.All)]
[HttpGet]
public IHttpActionResult Breakdown()
    {
    var count = dataService.GetAll()
                .Select(x => x.TestResultTypeId)
                .Distinct()
                .Count();

    return Ok(count);
    }

本质上,对于CurrentTestResult集合中的所有实体,它返回集合中TestResultTypeId出现的不同。(这是一个微不足道的操作,但我简化了一个更复杂的真实生活场景)

这很容易做到 - 但我似乎无法首先CurrentTestResult过滤它应该操作的集合。

此请求,默认情况下对所有 CurrentTestResult 实体进行操作

localhost/app/odatareport/CurrentTestResult/Default.Breakdown

返回

{
@odata.context: "http://localhost/app/odatareport/$metadata#Edm.Int32",
value: 5
}

(正确的结果,有 5 种不同的类型)

然而,这个试图简单地先过滤掉它的请求失败了

localhost/app/odatareport/CurrentTestResult/Default.Breakdown?$top=2

返回

{
error: {
code: "",
message: "The query specified in the URI is not valid. The requested resource is not a collection. Query options $filter, $orderby, $count, $skip, and $top can be applied only on collections.",
innererror: {
message: "The requested resource is not a collection. Query options $filter, $orderby, $count, $skip, and $top can be applied only on collections.",
type: "Microsoft.OData.ODataException",
stacktrace: 
" at System.Web.OData.EnableQueryAttribute.ValidateSelectExpandOnly(ODataQueryOptions queryOptions) at System.Web.OData.EnableQueryAttribute.ExecuteQuery(Object response, HttpRequestMessage request, HttpActionDescriptor actionDescriptor, ODataQueryContext queryContext) at System.Web.OData.EnableQueryAttribute.OnActionExecuted(HttpActionExecutedContext actionExecutedContext)"
     }
  }
}

据我了解 ODATA 管道,为什么失败是有道理的。控制器方法将返回一个 IQueryable,然后将应用 ODATA $filter、$top 等。

我想要一个函数来对已经被过滤掉的集合进行操作。

我想要做的甚至可能吗?

我知道 Breakdown 方法本身有 .GetAll() ,但必须有一种方法可以在方法之前应用过滤 -

否则,这一切都是毫无意义的......

4

1 回答 1

4

两种选择:

1) ODATA 有一个$count端点(请参阅,但有两种形式$count- 端点api/collection/$count和系统查询选项api/collection?$count=true;您需要端点)返回集合的计数(可以用 过滤EnableQuery)。将您的函数视为任何其他GET收集方法并返回您希望计算的查询(在本例中为 distinct TestResultTypeId),然后只需要求客户端请求其$count端点。

2)为您的操作方法定义一个ODataQueryOptions<T>参数并手动应用选项:

public IHttpActionResult Get( ODataQueryOptions<CurrentTestResult> queryOptions )
{
    // base query with ODataQueryOptions applied
    var query = queryOptions.ApplyTo( dataServcie.GetAll() ) 
        as IQueryable<CurrentTestResult>;

    // get distinct TestResultTypeId's and then count
    var count = query.Select(x => x.TestResultTypeId)
            .Distinct()
            .Count();

    return Ok( count );
}

我现在在移动,所以无法测试,但这应该足够接近(如果不准确),可以让你到达你需要去的地方。如果有任何问题,请告诉我,我会更新答案。

于 2017-09-29T23:16:44.050 回答