【问题标题】:Pushing OData filters down through layers通过层向下推送 OData 过滤器
【发布时间】:2014-07-26 20:06:04
【问题描述】:

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

  • DataAccess - 该项目涉及多个 DB 和 Web 服务。这一层定义了每个接口的接口。它公开了每个源的本机类型(数据库的 EF 类型、Web 服务的 SOAP 定义的类型等)。假设它公开了一个 EFProject 和 SoapProject。
  • Repository - 该层缝合来自各种来源的结果以形成单个实体,并公开它。我们称之为 ModelProject
  • 服务 - 将 REST 属性添加到实体(操作链接等)。这会公开一个 ProjectDTO。
  • WebApi - 控制器直接吐出 ProjectDTO。

我正在尝试实现 OData,特别是对非常大的查询的结果进行分页。我看过很多例子,但它们似乎都是直接暴露源对象,然后将它们映射到控制器中的最终DTO。

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

【问题讨论】:

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


    【解决方案1】:

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

    1. 公共 IQueryable Get(ODataQueryOptions queryOptions)
    2. public IQueryable Get(int key, ODataQueryOptions queryOptions)

    以下是一个示例: 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

    【讨论】:

    • 谢谢,谭。问题是 ODataQueryOptions 对象旨在应用于 WebApi 层知道的对象集合(我的问题中的 ProjectDTO)。我需要在存储库层应用查询,以便 EF 将其解释为可以针对数据库运行的东西,而不是最终的对象集合。
    • ODataQueryOptions 不仅适用于集合,也适用于单个对象(例如 $select)。通过实现这两种方法,您可以将选项转换为方法体内的其他选项。例如,将 ODataQueryOptions.SelectExpandQueryOption 转换为 EF 可以使用的内容,然后直接使用它。
    • 这就是我现在正在做的事情。我正在有效地编写自己的 ODataQueryOptions 版本,以将查询下放到适当的层。我的问题更多的是关于是否有任何东西可以进行这种翻译,或者是否有其他方法。
    • 我不知道其他方法。
    【解决方案2】:

    有没有办法将 ODataQueryOptions 从一种类型“转换”为另一种类型?还有其他我不知道的方法吗?

    有一种方法可以将IQueryable<DomainModel> 实际翻译成IQueryable<DtoModel>

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

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

    我在我从事的一个项目中非常成功地使用了它:只要你只依赖 AutoMapper 投影来转换类型,它应该可以正常工作。

    当然,你不能用这种方式做很多花哨的映射。项目方法将无法应用您创建的所有类型的映射,因此我建议您查看前面的文档。

    您还必须记住,原始的IQueryable 需要暴露在存储库层之外才能正常工作,否则查询将执行得太早。有些人会发现这违反了边界,并会主张在存储库层内实现查询,但我对那个特定方面没有意见。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-02
      • 1970-01-01
      • 2016-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多