【发布时间】:2021-12-01 11:02:51
【问题描述】:
想象一下,我有一个房地产网站,您可以通过它向不同的房地产经纪人询问特定的房地产。不同的查询方法可能具有与之关联的不同计费计算,并且并非所有代理都会启用每种计费模型。
public class EmailEnquiryBillingModel : ValueObject
{
public string EmailAddress { get; set; }
public decimal CostPerEnquiry { get; set; }
}
public enum DayOfWeek
{
Monday,
Tuseday,
// etc.
}
public class OpeningHours : ValueObject
{
public DateTime OpeningTime { get; set; }
public DateTime ClosingTime { get; set;}
}
public class PhoneEnquiryBillingModel : ValueObject
{
public PhoneEnquiryBillingModel()
{
OpeningHours = new Dictionary<DayOfWeek, OpeningHours>();
}
public int PhoneNumber { get; set; }
public IDictionary<DayOfWeek, OpeningHours> OpeningHours { get; set; }
}
public class EstateAgent : Entity
{
public string Name { get; set; }
public EmailEnquiryBillingModel EmailEnquiryBillingModel { get; set; }
public PhoneEnquiryBillingModel PhoneEnquiryBillingModel { get; set; }
}
NHibernate 具有组件(值对象)的语义,如果组件中的每个属性都为 null,则该组件也将为 null。
因此,通过适当的映射,您可以编写if(estateAgent.EmailEnquiryBillingModel != null),而不必检查电子邮件查询计费模型的每个单独属性,或者该模型是否有效:我们要么有模型,要么没有。这是一种检查是否启用了特定计费模式的简单而优雅的方法。
当您在一个组件中有一个集合时,问题就出现了,例如电话查询计费模式和不同的营业时间。 PhoneEnquiryBillingModel 和 OpeningHours 都不是实体。这些是合法的价值对象:我们不关心房地产经纪人是在周一上午 9 点这个还是周一上午 9 点 那个 开门,只关心它在周一上午 9 点开门。星期一。
因此,这感觉像是用 C# 表示此领域模型的语义正确方式。
然而,PhoneEnquiryBillingModel 包含一个集合(ProviderOpenHours),并且集合在 NHibernate 中不能为空,只能为空,这意味着 ProviderOpenHours 将始终为非空,即使房地产代理没有有意义地启用该查询模型。 (有关详细信息,请参阅:https://ayende.com/blog/4685/those-are-the-rules-even-when-you-dont-like-them)。
这意味着您不能像if(estateAgent.PhoneEnquiryBillingModel != null) 这样进行简单的检查,因为该对象总是不为空。
因此,对于某些计费模型,您可以进行空值检查以查看它们是否已启用,但对于其他计费模型,您必须找到另一种检查方式,具体取决于这些计费模型是否包含一套。
实际上,您需要了解计费模型的内部结构才能知道是否可以进行这种比较,这感觉就像您正在打破封装并更改基于域模型的关于 ORM 的规则。
有没有更好的建模方法?或者如果 NHibernate 没有电话号码或任何营业时间,可以让 NHibernate 在 PhoneEnquiryBillingModel 中序列化为 null?
【问题讨论】:
标签: nhibernate domain-driven-design