【问题标题】:IEnumerable vs IQueryable in OData and Repository PatternOData 和存储库模式中的 IEnumerable 与 IQueryable
【发布时间】:2018-08-04 02:58:33
【问题描述】:

我观看了 this 视频并阅读了 this 博客文章。这篇文章中有一些东西让我感到困惑;帖子的最后一部分。在最后一部分 Mosh 强调,Repository 永远不应该返回 IQueryable,因为它会导致性能问题。但我读到一些听起来矛盾的东西。

这是令人困惑的部分:

IEnumerable:从数据库中查询数据时,IEnumerable 在服务器端执行选择查询,在客户端将数据加载到内存中,然后过滤数据。因此做更多的工作并变得缓慢。

IQueryable:从数据库中查询数据时,IQueryable 在服务器端使用所有过滤器执行选择查询。因此,工作量减少并变得更快。

this is another answer 关于存储库模式中的 IQueryable 与 IEnumerable。

这些与 Mosh 的建议相反。如果这些都是真的,为什么我们不应该使用 IQueryable 而不是 IEnumerable。

还有别的,我们想使用 OData 的情况呢?如您所知,通过 OData 进行查询时,最好使用 IQueryable 而不是 IEnumerable。

还有一件事,使用 OData 查询电子商务网站 API 是好是坏。

请告诉我你的意见。

谢谢

【问题讨论】:

  • 我遇到了一些非常相似的事情,我已经确定没关系。如果您有一个公开 IQuerable Find(Expression predicate) 或类似内容的存储库 - 您可以传入过滤器的初始要求集,然后允许应用程序完成其余工作。如果 IQuerable 正确实现,则实际执行将推迟到需要时。
  • 我能想到的唯一真正的争论是您是否需要选择字段的子集而不是整个对象。您仍然可以这样做,但使用自定义提供程序会变得更加困难。

标签: odata ienumerable repository-pattern iqueryable


【解决方案1】:

存储库永远不应返回IQueryable。但不是因为性能。这是由于复杂性。存储库旨在降低业务层的复杂性。

购买公开IQueryable 会以两种方式增加复杂性:

  • 您将持久性知识泄漏到业务领域。对于编写有效查询的底层 Linq to Sql 提供程序,您必须了解一些事情。
  • 您必须设计业务实体以便可以查询它们(即不是纯粹的业务实体)。

例子:

var blockedUsers = _repository.GetBlockedUsers();

//vs

var blockUsers = _dbContext.Users.Where(x => x.State == 1);
var user = _repos.GetById(1);
//and an enum is used internally in the user class
user.Block(); 
_repos.Update(user);

// vs 
var user = _dbContext.Users.FirstOrDefault(x => x.Id == 1);
user.State = 1;
_dbContext.SaveChanges();

通过将所有内容封装在存储库后面,您可以以一种易于使用的方式设计业务实体(子实体、枚举、日期管理等)。并且您设计存储库,以便可以有效地存储这些实体。没有妥协和更容易维护的代码。

关于 OData:不要使用存储库模式。在这种情况下,它不会增加任何价值。

如果您坚持在您的业务领域中使用IQueryable,请不要使用存储库模式。它只会使事情复杂化而不会增加任何价值。

最后:

使用正确设计的存储库的业务逻辑更容易测试(单元测试)。混合了 LINQ 和业务逻辑的代码必须始终是集成测试(针对 DB),因为 Linq to Sql 与 Linq to Objects 不同。

【讨论】:

    猜你喜欢
    • 2012-02-15
    • 1970-01-01
    • 2015-12-21
    • 1970-01-01
    • 2014-02-03
    • 2020-04-28
    • 2011-06-09
    • 2011-05-16
    • 2014-11-09
    相关资源
    最近更新 更多