DDD引用大型数据集/注入存储库?

时间:2014-06-24 15:24:11

标签: domain-driven-design repository-pattern

我正在努力寻找以下最佳解决方案。我需要确定一个国家是否是" InUse",(例如,当前由地址引用)。

我在NHibernate中映射了以下简化模型:

class Address
{
  public Country Country {get; set;}
}

class Country
{
  public List<Address> Addresses {get; set;}

  bool IsInUse()
  {
    return Addresses.Any();
  }
}

在Country上使用IsInUse方法是低效的,因为它会导致所有国家/地区的加载(.Any()在内存中执行)。此外,Country并不真正需要了解地址,它纯粹适用于IsInUse方法。所以,从消费者的角度来看,我喜欢上面的例子,感觉域对象应该公开一个IsInUse方法,但它不会执行并包含不必要的关系。

我能想到的其他选择是;

  1. 只需使用存储库并直接从服务层调用它。存储库可以封装一个简单地发出SELECT COUNT(*)而不是SELECT *的调用,就像上面的延迟加载选项一样。此选项使IsInUse逻辑完全位于域层之外。
  2. 将存储库注入IsInUse(),调出与上面相同的内容。我已经读到这是非常糟糕的DDD练习。
  3. 是否有人对此问题有任何建议或更好的解决方案。

    希望以上内容有道理......谢谢。

3 个答案:

答案 0 :(得分:1)

我建议您每次执行查询时都不要计算它。归一化IsInUse。每次在国家/地区添加或删除地址时,您都可以确定该国家/地区是否正在使用并保存该值。

如何确定该值是另一个故事,并且有各种各样的技术,包括在保存地址时立即确定它并更新国家/地区的IsInUse值,或者甚至使用消息传递,如果它们恰好是不同的实体的BC。

答案 1 :(得分:0)

感觉您正在编写域概念来解决您的问题。你能告诉我们为什么你需要知道一个国家是否在使用?

存储库非常适合捕获语言和聚合持久性,而不是查询。您基本上是在向您的数据提问。也许将这个逻辑完全移到查询端?另请参阅http://www.jefclaes.be/2014/01/repositories-where-did-we-go-wrong_26.html

也许还有另一种方法可以跟踪所有正在使用的国家/地区。这些地址来自哪里?也许您可以在注册地址时引入域事件 - ,将国家/地区添加到正在使用的国家/地区列表中,这样您就可以查询较小的列表。

答案 2 :(得分:0)

我设计的域实体没有来自NHibernate或任何其他持久性机制的概念。如果这意味着通过使用NHibernate,您需要引入双向映射属性作为标准,那么我只会在您的存储库中使用您的NHibernate实体,并为您的域模型设计一组单独的实体并在两者之间进行映射。从您的业务角度来看,CountryAddress一无所知,这似乎是合理的。

将存储库注入域实体或使用延迟加载通常会违反DDD,并在序列化实体或丢失数据库上下文时导致问题。

你的IsInUse问题可以通过缓存查询来解决(不是所有的东西都必须在存储库中),也许你可以创建一个CountryStatistics类来处理这个问题?或者您可以保留一个单独的持久性国家/地区列表,每次使用从未使用过的国家/地区创建新地址时,该列表都会更新。