我有一个使用实体框架和 Odata 的 ASP.NET Web API 应用程序。
我想在使用 GET 时修改查询结果...目前,在控制器中,您实际上只需将 EntityFramework 数据实体传递回 Odata 处理程序...
[EnableQuery]
public IQueryable<myEntity> GetLineItem()
{
return db.myEntities;
}
通过简单地返回一个子集来预先添加 Odata 传入的任何查询是很简单的
return db.myEntity.Where(myEntity => myEntity.Name == "Bob")
Odata 会将 $filter 查询字符串参数中的任何内容添加到此处传入的表达式中,您将获得这些结果的子集。
但是,一旦查询执行并且 SQL 结果被解析为实体对象,我想迭代结果。
我尝试创建一个实现 IQueryable 接口并挂钩到 GetEnumerator 方法的包装器,以及同样的 IProvider 并挂钩到执行方法。 Odata 似乎没有使用其中任何一个。
有办法做到这一点吗?
您可以通过实施过滤器来做到这一点。过滤器只是一个属性,您可以将其应用于操作(控制器的方法)、控制器(控制器的类)或为整个应用程序注册。
此过滤器应用于管道上的某个步骤:有一个管道从传入的 HTTP 请求到控制器操作,然后返回到响应,并且您可以在此管道的不同位置包含过滤器,以修改数据流过这条管道。
你特别需要继承
ActionFilterAttribute
,并对OnActionExecuted
进行后处理,它是在控制器的动作执行后执行的。
文档:
最后一个类是
OnActuonExecuted
方法的参数类型,包含您可以修改的响应。
本文第一部分包含对动作过滤器的解释: WEB API 2 使用 ActionFILTERATTRIBUTE、OVERRIDEACTIONFILTERSATTRIBUTE 和 IOC 注入
基于 Ihar 的 answer,这里是应用查询选项然后修改结果集合的完整示例。
public async Task<IHttpActionResult> Get(ODataQueryOptions<MyModel> options)
{
var query = _service.Query();
var result = ((IQueryable<MyModel>)options.ApplyTo(query, new ODataQuerySettings()))
.ToArray();
foreach (var model in result)
{
model.SomeNonQueriedValue = "Something else";
}
return Ok(result);
}
使用 OData 时,您不必从控制器返回
IQueryable
。检查“直接调用查询选项”部分https://learn.microsoft.com/en-us/aspnet/web-api/overview/odata-support-in-aspnet-web-api/supporting-odata-query-选项
对于您的情况,它看起来像:
public HttpResponseMessage Get(ODataQueryOptions<myEntity> opts)
{
var settings = new ODataValidationSettings();
opts.Validate(settings);
var intermediateResult = opts.ApplyTo(db.myEntities).ToArray();
var result = // change intermediateResult as you wish.
return result;
}