【问题标题】:OData-v4 - operating on an entity collection then performing a FunctionOData-v4 - 在实体集合上操作然后执行功能
【发布时间】:2017-09-30 09:23:53
【问题描述】:

在我的 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() 在其中,但必须有一种方法可以在方法之前应用过滤 -

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

【问题讨论】:

    标签: c# entity-framework odata odata-v4


    【解决方案1】:

    两种选择:

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

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

    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 );
    }
    

    我现在处于移动状态,因此无法进行测试,但这应该足够接近(如果不准确),以便将您带到您需要去的地方。如果有任何问题,请告诉我,我会更新答案。

    【讨论】:

    • 确实非常接近 - 我仍然有一个问题 - 我按照你说的做了 - 当我单步执行代码时,它会应用选项 - 但是,在客户端中,我得到了这个:@ 987654322@
    • 没关系,我忘了删除 AllQueryOptions 属性 - 再次感谢!
    • 很好,没问题
    猜你喜欢
    • 2014-09-17
    • 2020-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-13
    • 1970-01-01
    相关资源
    最近更新 更多