【问题标题】:Is it possible to hide IQueryable from controllers yet still allow for pagination and sorting?是否可以从控制器中隐藏 IQueryable 但仍允许分页和排序?
【发布时间】:2011-07-10 18:58:46
【问题描述】:

背景

我正在使用工作单元/存储库模式开发 Web 应用程序。我选择了一个与存储库交互的服务层。存储库返回 IQueryable 给服务层,服务层返回 List 给控制器。

我决定不将 IQueryable 返回到控制器,以确保查询将被重用并放置在正确的层 - 服务层。也因为以后可能需要网络服务。

问题

在控制器级别允许分页和排序而不在控制器级别公开 IQueryable 的最佳方法是什么?

一种选择是向所有可能返回多个实体的服务函数添加参数,但这似乎并不理想。或者,我仍然可以对返回的列表进行分页,但这会导致大量不必要的数据访问。

编辑澄清

我的存储库具有如下功能:

public IQueryable<T> GetAll()
{
    return objectSet;
}

我的服务具有如下功能:

public List<Person> GetAllPeople()
{
    return repository.GetAll().ToList()
}

我很高兴存储库将 IQueryable 返回到服务,因为这允许服务具有以下功能:GetPersonByName、GetPersonByEmail 等

但我正在寻找一种替代方法,而不是仅在“PageNumber”和“PageSize”参数之上提供 GetAllPeople 函数。

【问题讨论】:

  • 我会传递参数以在服务层对列表进行分页,例如 PageSize、total 等。而不是在控制器上进行。
  • IEnumerable 只允许分页 once 据我了解,所有内容都已加载到内存中。如果有大量行,这将是有问题的。
  • 仅通过 Enumerable 返回类型返回 IQueryable 类型不会被拉入内存。你实际上必须做一些事情来触发延迟查询的执行,比如调用 ToList()。

标签: c# asp.net-mvc linq iqueryable


【解决方案1】:

在尽可能靠近底层存储的地方实现分页绝对是最有效的。考虑到这一点,我认为在您的服务层方法中接受分页参数是非常值得的。

我的 0.02 美元:这是理论不应胜过实用性的一种情况。

【讨论】:

  • 谢谢 Riko,我现在可能不得不使用分页参数,但我希望随着服务层的增长,这可能不是理想的。
  • @havok - 你是什么意思“不会是理想的”?您在谈论每种方法的 4 个额外参数,这些参数需要几秒钟才能输入。没什么大不了的。根据经验,您永远不应允许执行没有最大结果数的查询。这会导致未来出现问题。
  • @jfar 4 个额外参数?!创建一个类并使用一个。
  • @jfar - 你是对的,它甚至可能没有多达 4 个,但是在使用多种方法的多个服务上,我可以看到它可能会变得很痛苦。所以我希望有一个中间立场的解决方案。
  • @Ryan - 我的截止值是 5-6 个参数。 ;) - @havok - 奇怪的观点。我认为你关心的只是一个普通的软件开发。
【解决方案2】:

如果我正确理解您的问题,这里有一个解决方案: 您可以在任何 IQueryable 上调用 AsEnumerable(),后续操作将使用 Enumerable (LINQ to Objects) 实现,而不是 Queryable 版本。

我在 MSDN 上写了很多细节:http://msdn.microsoft.com/en-us/vcsharp/ff963710

【讨论】:

  • 谢谢比尔,我喜欢这篇文章。根据您的回答,我已经编辑了我的问题以提供更多信息,我不确定我可以在 AsEnumerable() 中插入的位置。您能否提供更多细节?
【解决方案3】:

我曾经遇到过类似的问题,并写了一篇关于它的博客文章here

你的情况并不完全一样,但是Repository模式的概念和局限是。

基本上我选择做的是用查询对象模式替换存储库模式。查询对象包含用于过滤、排序和分页的参数,然后在服务级别被包裹在 IQueryable 周围。

这样我的控制器和我的服务层之间就有了一个一致的接口,如果我更改了数据存储(如果你将来离开一个 LINQ 包装的存储怎么办?)并且控制了多少IQueryable 被暴露。

【讨论】:

    【解决方案4】:

    您可以为IQueryable 结果创建一个包装器,这样您就只允许分页和排序。类似于in this article 的解释。但我建议将那里提出的两个接口(@98​​7654323@ 和 IPageable)合并到一个包装器中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-08
      • 1970-01-01
      • 1970-01-01
      • 2011-02-25
      • 1970-01-01
      • 1970-01-01
      • 2015-03-20
      • 2016-05-31
      相关资源
      最近更新 更多