如何避免首先以DDD友好方式检索聚合根以进行优化?

时间:2015-03-20 12:38:21

标签: database performance domain-driven-design ddd-repositories

我已经编写了一个应用程序并尝试尽可能使用DDD。我遇到了一个我不确定如何解决的问题。大多数系统是通过Web前端通过用户驱动的,应用程序的请求量非常低且本质上非常CRUDy。但是,系统的一部分可以集成到其他在线系统中,并且请求量很大。我们从以往的经验中已经知道,我们必须尽可能地简化这一点。

场景是我们想要添加创建实体(如果它不存在),但如果确实存在则添加到聚合根。

var foo = fooRepo.Get(id);
if (foo != null)
{
    foo.Bars.Add(new Bar("hello"));
    fooRepo.Add(foo);
}
else
{
    var foo = new Foo();
    foo.Bars.Add(new Bar("hello"));
    fooRepo.Add(fooo);
}

如果操作是由用户发起的,我们不介意,因为它的数量很少。但系统生成的是一个额外的数据库,以确定它是否存在。我们已经确定这对我们来说是瓶颈。

如何以DDD方式执行上述操作,但避免额外的数据库访问。我开始研究CQRS,因为我认为模式的一部分是没有存储库,所以我可以执行命令。但我发现大多数CQRS示例仍然使用repos,并且在大多数示例中仍然对聚合根执行get操作,然后对它们进行操作然后将其保存回来。

显然,存储库不能在我的场景中工作,因为我无法将问题视为内存中的项目集合。 (事实上​​,只有很多数据甚至可以缓存所有内容)。性能最好的是直接写入数据库。

在这种情况下有什么可以做的吗?或者我应该编写例外代码?

1 个答案:

答案 0 :(得分:1)

如果额外的往返实际上是一个问题(我不确定),您可以将FooRepository.AddOrUpdate(foo, bar)方法实现为直接INSERT INTO ... IF NOT EXISTSMERGE INTO SQL语句为什么会这样。)

ETL或批量导入过程很少遵循相同的规则或者与基于UI的规则一样经历相同的层。应用程序层通常是一个单独的层,您甚至可能希望在某些情况下绕过域层。

考虑事务方面的第二个输入流可能是一个好主意(这些系统生成的更改是批量还是单位,您是否希望以隔离两个并发最终用户事务的方式隔离它们,等等。?)并根据它创建一个特定的应用层。

如果事实证明,即使这样你也会受到集合设计的限制,你可能想要完全缩短域层。