我正在努力寻找以下最佳解决方案。我需要确定一个国家是否是" 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方法,但它不会执行并包含不必要的关系。
我能想到的其他选择是;
是否有人对此问题有任何建议或更好的解决方案。
希望以上内容有道理......谢谢。
答案 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实体,并为您的域模型设计一组单独的实体并在两者之间进行映射。从您的业务角度来看,Country
对Address
一无所知,这似乎是合理的。
将存储库注入域实体或使用延迟加载通常会违反DDD,并在序列化实体或丢失数据库上下文时导致问题。
你的IsInUse
问题可以通过缓存查询来解决(不是所有的东西都必须在存储库中),也许你可以创建一个CountryStatistics
类来处理这个问题?或者您可以保留一个单独的持久性国家/地区列表,每次使用从未使用过的国家/地区创建新地址时,该列表都会更新。