Rod*_*eek 3 c# entity-framework odata asp.net-web-api angularjs
我有一个设置,其中我获得了一个 WebApi OData 服务,该服务返回:Customers。返回客户的代码是:
public IHttpActionResult GetCustomers(ODataQueryOptions<Customer> queryOptions)
{
return Ok(context.Customers.Where(i => i.IsActive).AsQueryable());
}
Run Code Online (Sandbox Code Playgroud)
因此,GetCustomers 方法返回所有活动客户的 IQerable 结果。出于历史目的,我们将所有客户保留在数据库中,但是当删除客户时,我们将 IsActive 字段设置为 false。
OData 设置是使用简单的 builder.EntitySet 创建的,用于为实体构建 Url。
EntitySetConfiguration<Customer> customers = builder.EntitySet<Customer>("customers");
Run Code Online (Sandbox Code Playgroud)
这完美无缺。我有一个 Angular 前端,它使用 $http 调用来接收客户等。
但是,客户可以在数据库中包含相关联系人。为了在 Angular 前端获取联系人,我使用了 OData 的 $extend 功能:
odata/customers?$expand=contacts
Run Code Online (Sandbox Code Playgroud)
这也很好用。我收到了所有相关联系人的客户。但是,正如您所猜想的那样,我只想接收应返回具有 IsActive 的联系人。IQueryable 功能将所有结果返回给我。
我知道我可以使用单独的 Odata 调用来获取联系人,但我真的很想使用 $expand 功能在一次调用中获取所有数据。我知道我也可以在客户端进行过滤(使用:$filter)。但我想在 WebApi 部分正确设置它,因此客户端不必关心过滤非活动结果。
我似乎无法弄清楚如何正确实现这一目标。有人可以帮助我走上正轨吗?
EntityFramework.DynamicFilters是我所知道的 Entity Framework 最伟大的工具之一。它跳入了经常请求但直到 EF6 从未实现过滤Incudes功能的差距。它依赖于 EF 的拦截 API,并在暴露一个非常简单的接口的同时完成了修改表达式的繁重工作。
在你的情况下,你可以做的是这样的:
using EntityFramework.DynamicFilters;
// In OnModelCreating (DbContext)
modelBuilder.Filter("CustomerActive", (Customers c) => c.IsActive);
Run Code Online (Sandbox Code Playgroud)
就这样!现在到处Customers查询,无论是直接查询,还是通过导航属性或在Includes 中,谓词都会添加到查询中。
你想要所有的客户吗?您可以通过执行以下操作简单地关闭每个上下文实例的过滤器
context.DisableFilter("CustomerActive");
Run Code Online (Sandbox Code Playgroud)
到目前为止,我只发现了一个小故障(或警告)。如果有两个实体,Parent并且Child有一个过滤器Parent不返回任何记录,那么这个查询......
context.Children.Include(c => c.Parent)
Run Code Online (Sandbox Code Playgroud)
...不返回任何东西。但是,从查询的形状来看,我希望它返回Child父项为空的实体。
这是因为在 SQL 中有一个INNER JOIN介于ParentandChild和 的谓词,Parent其计算结果为false。AnOUTER JOIN会给出预期的行为,但我们当然不能要求这个库变得那么聪明。
| 归档时间: |
|
| 查看次数: |
1231 次 |
| 最近记录: |