Entity framework OData v4结果后处理(适用于v3,不适用于v4)

Entity framework OData v4结果后处理(适用于v3,不适用于v4),entity-framework,asp.net-web-api,odata,Entity Framework,Asp.net Web Api,Odata,我有一个WebAPI服务器(带有EF6.x),我需要对控制器中OData查询的结果集进行一些后处理。在客户端,我使用一个DevEx网格和它们的odatanstantfeedbacksource 没有后期处理,一切正常,例如: 美元计数 注意:对于ODataV3,上面的工作很好。只有v4在不使用[EnableQuery]时才会出现异常 如果我重新添加[EnableQuery]属性,这个简单的$count查询适用于ODATA v4,但是对于更复杂的查询,返回给客户端的数据会变得混乱(可能是由于$sk

我有一个WebAPI服务器(带有EF6.x),我需要对控制器中OData查询的结果集进行一些后处理。在客户端,我使用一个DevEx网格和它们的odatanstantfeedbacksource

没有后期处理,一切正常,例如:

美元计数

注意:对于ODataV3,上面的工作很好。只有v4在不使用[EnableQuery]时才会出现异常

如果我重新添加[EnableQuery]属性,这个简单的$count查询适用于ODATA v4,但是对于更复杂的查询,返回给客户端的数据会变得混乱(可能是由于$skip等被我和EnableQuery属性应用)

例如,当您向下滚动时,DevEx网格会生成以下查询: ?$orderby=ItemNo&$skip=300&$top=201

结果(客户端):返回的密钥数意外:0。预期:201

我假设我需要删除EnableQuery属性,因为我正在手动应用查询选项,但为什么在我这样做时会出现“无法转换为原始字符串”异常


我如何在这种情况下正确实施后处理?

我就此向Microsoft提出了支持请求,他们最终确定这是ODATA v4中的一个错误,并创建了此错误报告:

解决方法是检查查询是否是计数查询,如果是,则返回Ok(query.count())

下面是一个更完整的示例代码片段/POC,它可以很好地与ODATA v4配合使用:

private static ODataValidationSettings _validationSettings = new ODataValidationSettings();

[ODataRoute("Customers")]
public IHttpActionResult Get(ODataQueryOptions<CustomerLookup> queryOptions)
{
    queryOptions.Validate(_validationSettings);
    var query = queryOptions.ApplyTo(Context.CustomerLookup) as IQueryable<CustomerLookup>;
    if (queryOptions.Context.Path?.Segments.LastOrDefault() is CountSegment)
        return Ok(query?.Count());

    var resultList = new List<CustomerLookup>();
    foreach (var customer in query)
    {
        customer.Address = "1234_" + customer.Address;
        resultList.Add(customer);
    }

    return Ok(resultList.AsQueryable());
}
private static ODataValidationSettings_validationSettings=new ODataValidationSettings();
[ODataRoute(“客户”)]
公共IHttpActionResult获取(ODataQueryOptions查询选项)
{
queryOptions.Validate(_validationSettings);
var query=queryOptions.ApplyTo(Context.CustomerLookup)可查询;
if(queryOptions.Context.Path?.Segments.LastOrDefault()为CountSegment)
返回Ok(查询?.Count());
var resultList=新列表();
foreach(查询中的var客户)
{
customer.Address=“1234”+customer.Address;
结果列表。添加(客户);
}
返回Ok(resultList.AsQueryable());
}
//[EnableQuery]
public IHttpActionResult GetItems(ODataQueryOptions<Item> queryOptions)
{
    queryOptions.Validate(_validationSettings);
    var query = queryOptions.ApplyTo(Context.Items, new ODataQuerySettings()) as IQueryable<Item>;
    var resultList = new List<Item>();
    foreach (var item in query)
    {
        item.OrdStat = "asf"; // Some post-processing
        resultList.Add(item);
    }
    return Ok(resultList.AsQueryable());
}
Microsoft.OData.ODataException
  HResult=0x80131509
  Message=The value of type 'System.Linq.EnumerableQuery`1[[SomeService.Model.Item, SomeService.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' could not be converted to a raw string.
  Source=Microsoft.OData.Core
  StackTrace:
   at Microsoft.OData.RawValueWriter.WriteRawValue(Object value)
if (queryOptions.Context.Path?.Segments.LastOrDefault() is CountSegment)
    return Ok(query?.Count());
private static ODataValidationSettings _validationSettings = new ODataValidationSettings();

[ODataRoute("Customers")]
public IHttpActionResult Get(ODataQueryOptions<CustomerLookup> queryOptions)
{
    queryOptions.Validate(_validationSettings);
    var query = queryOptions.ApplyTo(Context.CustomerLookup) as IQueryable<CustomerLookup>;
    if (queryOptions.Context.Path?.Segments.LastOrDefault() is CountSegment)
        return Ok(query?.Count());

    var resultList = new List<CustomerLookup>();
    foreach (var customer in query)
    {
        customer.Address = "1234_" + customer.Address;
        resultList.Add(customer);
    }

    return Ok(resultList.AsQueryable());
}