2012-08-02 173 views
2

我想遵循總體設計原則,並想出了我需要幫助的情況。我的聚合根是一個Customer對象。 Customer對象具有Address對象的子集合和Contact對象的子集合。DDD聚合根子關係NHibernate映射

A Contact可以參考Customer集合下的AddressCustomer對象具有唯一的ID,而對象AddressContact具有本地ID,因此數據庫中的主鍵爲CustomerIdAddressId

這裏是簡化類:

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 

當我試圖映射我與功能NHibernate實體我的問題來了。由於Address對象具有CustomerIdAddressId的組合鍵,因此NHibernate不會重複使用聯繫人表中的列CustomerId。當我嘗試保存聚集時,我收到一個異常,說有更多的值比有參數。發生這種情況的原因是地址對象具有複合ID,並且不與Contact對象共享CustomerId列。

我可以看到解決這個問題的唯一方法是在Contact表中添加一個AddressCustomerId列,但現在我有一個重複的列CustomerIdAddressCustomerId是相同的值。反正有這種行爲嗎?

回答

0

據我所知,NHibernate沒有辦法共享列。我最終選擇了幾年來一直使用的解決方案。我使用GUID作爲NHibernate的ID並使用int代理鍵來查詢。這個解決方案對我來說工作得很好,但我只想減少數據庫中的一些浪費。

1

如果地址和聯繫人都不具有客戶聚合之外的身份,則應將其映射爲組件集合。另外,是否需要客戶地址和客戶 - 聯繫人關係是雙向的?是否需要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); 
       }); 
      }); 
    } 
} 

在映射中,地址和聯繫人集合被映射爲組件。這意味着他們不需要擁有自己的身份,因此不需要個人映射課程。然而,在這個模型中,聯繫人的地址將與聯繫人數據本身存儲在同一行中,我相信這是一個好的模型(與更規範化的模型相反)。

+0

我按照自己的方式設計它的原因是因爲我可以從數據庫中查詢單個聯繫人,而無需首先加載Customer對象。地址和聯繫人是實體,應具有本地標識符。客戶可以擁有多個獨立於聯繫人的地址,並且客戶可以擁有多個獨立於該地址的聯繫人。我對DDD相當陌生,但我認爲實體可以引用聚合根內的其他實體,這意味着實體需要本地身份。 – awilinsk 2012-08-03 11:10:47