DDD存储库EF性能



我想知道使用DDD的人如何通过使用EF和返回带子级的聚合根的存储库模式来解决潜在的性能问题。

例如,家长-----儿童A

甚至如Parent-----儿童A-------儿童A2

  1. 如果我从存储库中带回聚合根的数据并使用导航属性EF,那么就会触发另一个查询,因为它正在使用延迟加载。这是一个问题,因为当我们处于循环中时,会遇到100多个查询
  2. 如果我使用"Include"语句从存储库中带回聚合根的数据以及子级的数据,这将从存储库及其父级中带回子级数据。然后,当我使用导航属性时,不会触发任何查询,因为数据已经在内存中了

第二种方法的问题是,我们的子对象的一些数据可能相当大,例如100000多条记录。显然,我不想为孩子在内存中存储100000多条记录。为了解决这个问题,我们决定使用分页一次选择10个,但另一个问题是,当我们试图对子项进行计算时,如总和、总数等,但我们只能在内存中对我们提取的10条记录进行计算。

我知道DDD的方法是将对象图的所有数据都放在内存中,然后遍历对象以获得需要显示的数据。

我们的团队中存在分歧,有些人认为我们应该将聚合根及其子对象一起拉回来,有些人则认为我们应该在聚合根的存储库中有一个方法,直接查询子对象的数据并拉回来子对象。

我只是想知道其他人是如何解决父母/孩子在内存中存储大量数据的性能问题的。

如果您必须处理性能问题,则必须使用第二种方法,该方法具有在存储库上公开的特殊方法,即存储库为您提供此类方法的点,否则您可以直接使用EF上下文/集。

如果你使用理论数据,理论是很好的——一旦你有了真实的数据,你就必须调整理论,使其在现实世界中发挥作用。

你也可以查看这篇文章(博客上有以下三篇文章)。它采取第二种方式,但它假装是第一种方式。它适用于Count,但也许你也可以将这个想法用于其他一些场景。

DDD方法并不总是提取所有所需的数据。我们使用了一种称为双重调度的模式。在这里,您可以使用聚合根方法(或域服务)所需的所有参数进行调用,还可以使用它传递"仅查询"存储库类型的接口参数。这使根或其子级能够决定需要什么额外的数据,以及何时应该通过简单地调用该注入接口上的方法来返回数据。

这种方法遵循DDD原则,即聚合根在提供可测试且高性能的域代码时不应意识到存储库实现。

最新更新