将OData过滤器向下推送到层

时间:2014-06-05 17:48:30

标签: entity-framework asp.net-web-api odata

我有一个包含以下图层的工作项目:

  • DataAccess - 该项目可以访问多个数据库和Web服务。该层定义了每个接口。它公开了每个源的本机类型(DB的EF类型,Web服务的SOAP定义类型等)。让我们说它暴露了一个EFP项目和SoapProject。
  • 存储库 - 此图层将来自各种源的结果定义为单个实体,并公开它。让我们称之为ModelProject
  • 服务 - 将REST属性添加到实体(操作链接等)。这暴露了ProjectDTO。
  • WebApi - 控制器直接吐出ProjectDTO。

我试图实现OData,专门用于分页非常大的查询结果。我已经阅读了很多例子,但它们似乎都直接暴露了源对象,然后将它们映射到控制器中的最终DTO。

我想以某种方式将ODataQueryOptions推送到存储库。这将允许我保留现有结构,并将查询逻辑传递给SQL。我理解,因为ODataQueryOptions引用了ProjectDTO类型,所以它们无法应用,直到该类型的对象可用。有没有办法去"翻译" ODataQueryOptions从一种类型到另一种类型?还有其他方法可以做到这一点,我不知道吗?

2 个答案:

答案 0 :(得分:0)

它能够更改ODataQueryOptions,并且控制器中的此类操作可供您自行处理选项:

  1. public IQueryable Get(ODataQueryOptions queryOptions)
  2. public IQueryable Get(int key,ODataQueryOptions queryOptions)
  3. 以下是关于此的示例: https://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/OData/v4/ODataQueryableSample/Controllers/OrdersController.cs

    供您参考,ODataQueryOptions的源代码是:https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.OData/OData/Query/ODataQueryOptions.cs

答案 1 :(得分:0)

  

是否可以将ODataQueryOptions从一种类型“转换”为另一种类型?还有我不知道的另一种方法吗?

有一种方法可以将IQueryable<DomainModel>实际转换为IQueryable<DtoModel>

我过去利用AutoMapper's projection functionality做过类似的事情。通过调用Project<TSource> / To<TTarget>方法,您可以将指向域模型的IQueryable更改为以Dto模型为目标的另一个IQueryable,而无需实际执行它。

这意味着您现在可以在DTO级别上执行任何OData操作,它们将通过投影传输到DAL层并转移到EntityFramework和SQL中。在这种情况下,不需要手动处理查询逻辑,因此您只需在API路由上使用[EnableQuery],然后让OData在生成的IQueryable<DtoModel>上做它的事情。

我在一个我从事的项目中非常成功地使用了此方法:只要您仅依靠AutoMapper投影来转换类型,它就可以正常工作。

当然,您不能通过这种方式进行很多精美的映射。项目方法将无法应用您创建的所有类型的映射,因此,我建议检查该方面的文档。

您还必须记住,原始IQueryable需要暴露在存储库层之外才能正常工作,否则查询将执行得太早。某些人会发现违反边界,会提倡在存储库层内部实现查询,但是我对此特定方面没有任何疑问。