Skip to main content
 首页 » 编程设计

c#之OData-v4之对实体集合进行操作然后执行函数

2024年02月04日33zhengyun_ustc

在我的 ODATA-v4 Controller 中,我有以下代码:

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 管道,失败的原因是有道理的。 Controller 方法将返回一个 IQueryable,然后将应用 ODATA $filter、$top 等。

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

我尝试做的事情是否可行?

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

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

请您参考如下方法:

两种选择:

1) ODATA 有一个 $count端点(参见 this 但有两种形式的 $count - 端点 api/collection/$count 和系统查询选项 api/collection?$count=true ;您需要端点)返回集合的计数(可以使用过滤EnableQuery)。像对待任何其他函数一样对待您的函数 GET collection 方法并返回您希望计算的查询(在本例中,不同的 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 ); 
} 

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