gpt4 book ai didi

c# - 存储库/IQueryable/查询对象

转载 作者:IT王子 更新时间:2023-10-29 04:49:25 26 4
gpt4 key购买 nike

我正在构建一个存储库,我在很多地方看到了两个不在存储库外公开 IQueryable 的原因。

1) 首先是因为不同的 LINQ 提供程序可能有不同的行为,这种差异应该包含在存储库中。

2) 第二个是防止服务级别开发人员修改数据库查询,从而意外导致性能问题。

我想问题 2 只能通过将所有查询逻辑保留在存储库中并且不允许任何形式的外部查询构建来避免吗?但这对我来说似乎有点不切实际。

问题 1 似乎可以通过使用数据对象模式来解决。

例如public IEnumerable<T> FindBy(Query query)

我的问题是,为什么我不直接传递一个 lambda 表达式,因为它独立于提供者,似乎可以为我提供与查询对象相同的功能,以及相同的分离级别?

例如public IEnumerable<T> FindBy(Expression<Func<T,bool>> predicate)

有什么理由不这样做吗?它是否违反了某些规则?最佳实践?我应该知道什么?

最佳答案

只返回一个IQueryable<T> .

在您编写另一段“存储库代码”之前,您将从阅读 Ayende 的文章 Architecting in the Pit of Doom - The Evils of the Repository Abstraction Layer 中受益匪浅。

毫无疑问,您的方法增加了不必要的复杂性。

Generic List of OrderBy Lambda 中另一个问题的所有代码除了用不必要和不熟悉的抽象来掩盖现有的有效 API 之外,没有做任何事情。

关于您的两个问题,

  1. LINQ 提供程序的行为确实不同,但只要您传递的谓词可以由 LINQ 提供程序处理,这就无关紧要。否则,您仍然会遇到同样的问题,因为您传递的是 Expression。 , 它被传递给 IQueryable无论如何最终。如果IQueryProvider实现不能处理你的谓词,那么它就不能处理你的谓词。 (如果您需要在无法翻译的进一步过滤之前进行评估,您可以随时调用 ToList())。

  2. 修改查询可能会导致性能问题,但更有可能公开急需的功能。此外,与为避免暴露 IQueryable 而提取比您需要的记录更多的记录所导致的性能问题相比,次优 LINQ 查询引起的性能问题可能要小得多。或者通过实际上不做任何事情的臃肿抽象级别系统地过滤任何数据访问逻辑(第一个威胁更为重要)。一般来说,这不会成为问题,因为大多数领先的 LINQ 提供商会在翻译过程中优化您的查询逻辑。

如果您想对前端隐藏您的查询逻辑,那么不要尝试创建通用存储库。使用实际的业务特定方法封装查询。现在,我可能错了,但我假设您对存储库模式的使用是受领域驱动设计的启发。如果是这种情况,那么使用存储库的原因是允许您创建一个主要关注域模型的持久性无知域。然而,使用这种通用存储库除了将语义从 Create Read Update DeleteFind Add Remove Save .那里没有嵌入任何真正的业务知识。

考虑一个

的意义(和可用性)
interface IPersonRepository 
{
Person GetById(int id);
IEnumerable<Person> FindByName(string firstName, string lastName);
}

相对于

interface IRepository<T> { 
IEnumerable<T> FindBy(Query<T> query);
}

此外,您能否指出使用 IRepository<T> 的好处?完全没有(而不是 IQueryable<T> )?

此外,请考虑使用通用方法,您实际上根本没有封装查询逻辑。您最终在外部构建它,这将导致更多额外的不必要代码。

*关于建议不要使用 IQueryable<T> 的资源的另一条注释, 是否值得查看它们的发布日期。曾经有一段时间,LINQ 提供程序的可用性非常有限(仅限于早期的 EF 和 LINQ-to-SQL)。当时暴露一个IQueryable<T>将导致与 Microsoft ORM 的一些更流行的替代品不兼容(LINQ-to-NHibernate 早已实现)。目前,LINQ 支持在严肃的 ORM .NET 库中几乎无处不在

关于c# - 存储库/IQueryable/查询对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11964578/

26 4 0