我正在尝试遵循聚合设计原则,并提出了我需要帮助的情况。我的聚合根是Customer
对象。 Customer
对象具有Address
个对象的子集合和Contact
个对象的子集合。
Contact
可以在Address
汇总下引用Customer
。 Customer
对象具有唯一ID
,Address
和Contact
对象具有本地ID,因此数据库中的主键为CustomerId
和{ {1}}。
以下是简化类:
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
当我尝试使用Fluent NHibernate映射我的实体时,我的问题出现了。由于CustomerId int not null PK,FK
ContactId int not null PK
AddressId int null FK
对象的复合键为Address
和CustomerId
,因此NHibernate不会在联系表中重用列AddressId
。当我尝试保存聚合时,我得到一个例外,说有比参数更多的值。发生这种情况是因为Address对象具有复合ID,并且不与CustomerId
对象共享CustomerId
列。
我能看到解决此问题的唯一方法是在Contact
表格中添加AddressCustomerId
列,但现在我有一个重复的列Contact
和{{1}是相同的值。反正有这种行为吗?
答案 0 :(得分:1)
如果Address和Contact都没有Customer聚合之外的标识,则应将它们映射为组件集合。此外,客户地址和客户 - 联系关系是否需要双向?是否需要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);
});
});
}
}
在映射中,地址和联系人集合被映射为组件。这意味着他们不需要拥有自己的身份,因此没有单独的映射类。然而,在这个模型中,联系人的地址将与联系人数据本身存储在同一行中,我认为这是一个很好的模型(而不是更标准化的模型)。
答案 1 :(得分:0)
据我所知,NHibernate无法共享列。我最终选择了几年来一直使用的解决方案。我使用GUID作为NHibernate的ID,并使用int surrogate键进行查询。这个解决方案对我来说效果很好,但我只想减少数据库中的一些额外浪费。