2010-07-15 55 views
2

是否將持久存儲庫接口注入到實體對象中是否存在持久性問題?通過不使用接口,我清楚地看到一個問題,但使用接口時真的有問題嗎?代碼是低於一個好或壞的模式,爲什麼?這是一個ddd反模式嗎?

public class Contact 
{ 
    private readonly IAddressRepository _addressRepository; 

    public Contact(IAddressRepository addressRepository) 
    { 
     _addressRepository = addressRepository; 
    } 

    private IEnumerable<Address> _addressBook; 
    public IEnumerable<Address> AddressBook 
    { 
     get 
     { 
      if(_addressBook == null) 
      { 
       _addressBook = _addressRepository.GetAddresses(this.Id); 
      } 
      return _addressBook; 
     } 
    } 
} 

回答

1

這不是一個好主意,但它可能適用於一些有限的情況。我對你的模型有點困惑,因爲我很難相信Address是你的聚合根,因此擁有一個完整的地址庫並不普通。根據你的例子,你可能實際上使用的是表格數據網關或者dao而不是存儲庫。

我更喜歡使用數據映射器來解決這個問題(ORM或類似的解決方案)。基本上,我會利用我的ORM將通訊簿視爲聚合根的「加載」屬性,即「聯繫人」。這具有如下優點:只要實體綁定到會話,就可以保存更改。

如果我沒有使用ORM,我仍然希望具體聯繫存儲庫實現設置AddressBook支持存儲(列表,或其他)的屬性。我可能讓存儲庫將枚舉設置爲了解其他數據存儲的代理對象,並根據需要加載它。

+0

的代碼是一個純粹的例子,不基於任何實際的代碼,但我同意AddressRepository是一個壞榜樣 – terjetyl 2010-07-15 18:12:03

+0

@JasonTrue,什麼是錯的地址爲一個聚合根?如果多個聯繫人共享相同的地址(例如,來自同一公司的沒有地址所有權的聯繫人),那麼您將如何建模?如果他們有獨特的身份,他們就不能成爲VO。 – smartcaveman 2012-09-10 18:52:07

0

您可以從外部注入加載函數。新Lazy<T>類型在.NET 4.0中派上用場爲:

public Contact(Lazy<IEnumerable<Address>> addressBook) 
    { 
     _addressBook = addressBook; 
    } 

    private Lazy<IEnumerable<Address>> _addressBook; 
    public IEnumerable<Address> AddressBook 
    { 
     get { return this._addressBook.Value; } 
    } 

還要注意的是,無論如何,當你從一個查詢提供讓他們IEnumerable<T> S可能會發生在本質上偷懶。但對於任何其他類型,您可以使用Lazy<T>

0

通常,當您遵循DDD時,您總是使用整個聚合。存儲庫始終會返回一個滿載的聚合根目錄。

在您的示例中,編寫代碼沒有太大意義(至少在DDD中)。聯繫人聚合將始終包含所有地址(如果它需要他們的行爲,我懷疑是誠實的)。

因此,通常ContactRepository會假設爲您構建整個Contact集合,其中Address是一個實體,或者很可能是此集合中的一個值對象。

由於Address是屬於(並因此由其管理)的聯繫人聚合的實體/值對象,因此它不會擁有自己的存儲庫,因爲您不應管理屬於此聚合之外的聚合的實體。

簡歷:總是加載整個聯繫人並調用其行爲方法來處理其狀態。

0

自從我問了這個問題2年後,這個問題有些被誤解了,我會盡力自己回答。

改編問題: 「商業實體類應該完全堅持無知嗎?」

我覺得實體類應該完全堅持無知,因爲你會在你的代碼庫中的許多地方實例化它們,所以它會很快變得混亂,總是需要將Repository類注入到實體構造器中,它看起來也不是很乾淨。如果您需要注入多個存儲庫,這變得更加明顯。因此,我總是使用單獨的處理程序/服務類來爲實體執行持久性作業。這些類的實例遠不如此頻繁,並且您通常可以更好地控制發生的位置和時間。實體類保持儘可能輕量級。

我現在總是有1個Repository pr聚合根,如果我需要一些額外的業務邏輯,當從存儲庫中提取實體時,我通常爲聚合根創建1個ServiceClass。

通過利用代碼的一個微調的例子中的問題,因爲它是一個壞榜樣,我會做現在這個樣子:

相反的:

public class Contact 
{ 
    private readonly IContactRepository _contactRepository; 

    public Contact(IContactRepository contactRepository) 
    { 
     _contactRepository = contactRepository; 
    } 

    public void Save() 
    { 
     _contactRepository.Save(this); 
    } 
} 

我不喜歡這樣寫道:

public class Contact 
{ 

} 

public class ContactService 
{ 
    private readonly IContactRepository _contactRepository; 

    public ContactService(IContactRepository contactRepository) 
    { 
     _contactRepository = contactRepository; 
    } 

    public void Save(Contact contact) 
    { 
     _contactRepository.Save(contact); 
    } 
}