我试图遵循聚合设计原则,并提出了一个我需要帮助的情况。我的聚合根是一个 Customer
对象。 Customer
对象具有 Address
对象的子集合和 Contact
对象的子集合。
Contact
可以引用 Customer
聚合下的 Address
。 Customer
对象具有唯一的 ID
,Address
和 Contact
对象具有本地 ID,因此主键在数据库中将是 CustomerId
和 AddressId
。
以下是简化的类:
public class Customer : AggregateRoot {
public virtual int CustomerId { get; protected set; }
public virtual IList<Address> Addresses { get; protected set; }
public virtual IList<Contact> Contacts { get; protected set; }
}
public class Address : Entity {
public Address(Customer customer, int addressId) {
this.Customer = customer;
this.AddressId = addressId;
}
public virtual Customer Customer { get; protected set; }
public virtual int AddressId { get; protected set; }
}
public class Contact : Entity {
public Contact(Customer customer, int contactId) {
this.Customer = customer;
this.ContactId = contactId;
}
public virtual Customer Customer { get; protected set; }
public virtual int ContactId { get; protected set; }
public virtual Address Address { get; set; }
}
数据库具有如下表:
客户
CustomerId int identity PK
地址
CustomerId int not null PK,FK
AddressId int not null PK
联系方式
CustomerId int not null PK,FK
ContactId int not null PK
AddressId int null FK
当我尝试使用 Fluent NHibernate 映射我的实体时,我的问题就出现了。由于 Address
对象具有 CustomerId
和 AddressId
的复合键,NHibernate 不会重用列 CustomerId
联系表。当我尝试保存聚合时,出现异常,提示值多于参数。发生这种情况是因为 Address 对象具有复合 ID,并且不与 Contact
对象共享 CustomerId
列。
解决此问题的唯一方法是在 Contact
表中添加 AddressCustomerId
列,但现在我有一个重复的列作为 CustomerId
和 AddressCustomerId
是相同的值。无论如何,有这种行为吗?
最佳答案
如果地址和联系人都没有客户聚合之外的身份,则应将它们映射为组件集合。另外,客户-地址和客户-联系人关系是否需要是双向的?是否需要addressId和contactId?如果模型被简化,这将起作用:
public class Customer
{
public virtual int CustomerId { get; protected set; }
public virtual IList<Address> Addresses { get; protected set; }
public virtual IList<Contact> Contacts { get; protected set; }
}
public class Address
{
public string Street1 { get; private set; }
public string Street2 { get; private set; }
public string City { get; private set; }
public string Region { get; private set; }
}
public class Contact
{
public string Name { get; private set; }
public string Email { get; private set; }
public virtual Address Address { get; set; }
}
public class CustomerMap : FluentNHibernate.Mapping.ClassMap<Customer>
{
public CustomerMap()
{
Table("Customers");
Id(x => x.CustomerId);
HasMany(x => x.Addresses)
.Table("CustomerAddresses")
.KeyColumn("CustomerId")
.Component(m =>
{
m.Map(x => x.Street1);
m.Map(x => x.Street1);
m.Map(x => x.City);
});
HasMany(x => x.Contacts)
.Table("CustomerContacts")
.KeyColumn("CustomerId")
.Component(m =>
{
m.Map(x => x.Name);
m.Map(x => x.Email);
m.Component(x => x.Address, ma =>
{
ma.Map(x => x.Street1);
});
});
}
}
在映射中,地址和联系人集合被映射为组件。这意味着它们不需要有自己的身份,因此不需要单独的映射类。然而,在此模型中,联系人的地址将与联系人数据本身存储在同一行中,我认为这是一个很好的模型(而不是更规范化的模型)。
关于nhibernate - DDD 聚合根子关系 NHibernate 映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11783414/