2010-03-26 27 views
2

我有一種理想關係,我相信會涉及到值對象繼承。不幸的是,這在NHibernate中不被支持,所以我提出的任何解決方案都不夠完美。如何建模NHibernate(或休眠)不易輕易支持的關係

假設:

  • 「項」實體有一個「位置」,可以在多種不同格式之一。
  • 這些格式完全不同,沒有重疊字段。
  • 我們將以數據中提供的格式處理每個位置,而不會嘗試從一種格式轉換爲另一種格式。
  • 每個項目只有一個位置。
  • 「SpecialItem」是Item的子類型,但是,它是唯一的,因爲它只有兩個位置。
  • 「組」實體聚合項目。
  • 「LocationGroup」是Group的子類型。
  • LocationGroup也有一個單一的位置,可以使用上述任何格式。
  • 雖然我感興趣的是由組項目,我也有興趣在能夠找到具有相同位置的所有項目,無論他們在哪個組。

我的數量道歉以上所列的規定,但恐怕再簡化一下並不能真正反映這種情況的困難。下面是上述可圖解:

Mapping Dilemma Diagram http://www.freeimagehosting.net/uploads/592ad48b1a.jpg

分析以上情況,我提出以下意見:

  • 我請客地點多態,指的是超類型,而不是亞型。
  • 邏輯上,位置應該是「值對象」而不是實體,因爲區分具有所有相同值的兩個位置對象是沒有意義的。因此,地點之間的平等應該基於實地比較而不是標識符。而且,值對象應該是不可變的,並且不應該允許共享引用。
  • 使用NHibernate(或Hibernate)通常會使用「component」關鍵字映射值對象,這會導致類的字段直接映射到表示包含類的數據庫表中。換句話說,數據庫中不會有單獨的「位置」表(因此位置將沒有標識符)。
  • NHibernate(或Hibernate)當前不支持值對象的繼承。

我的選擇,因爲我看到他們是:

  1. 忽視的事實是位置應該是值對象,並將它們映射爲實體。由於NHibernate支持實體繼承,這將處理繼承映射問題。缺點是我必須處理別名問題。(這意味着如果多個對象共享對相同位置的引用,那麼爲一個對象的位置更改值將導致該位置改變爲共享對相同位置記錄的引用的其他對象。)如果可能,我想避免這種情況。另一個缺點是實體通常通過ID進行比較。這意味着即使兩個位置對象的所有字段的值相同,也會將其視爲而不是。從商業角度來看,這是無效的和不可接受的。
  2. 將位置合併到一個類中,以便位置不再存在繼承關係。這將允許位置被視爲值對象,可以通過使用NHibernate中的「組件」映射輕鬆地進行處理。這種情況下的缺點是域模型變得更弱,更脆弱,維護性更差。
  3. 在hbm文件中執行一些「創意」映射,以強制將位置字段映射到包含實體的表格而不使用「組件」關鍵字。該方法由Colin Jack描述here。由於SpecialItem具有第二個位置以及另一個實體OwnGroup也具有位置這一事實,所以我的情況比他描述的情況更復雜。我可能可以使它工作,但映射將是非直觀的,因此未來其他開發人員很難理解和維護。另外,我懷疑這些棘手的映射可能無法使用Fluent NHibernate,所以我會利用使用該工具的優勢,至少在這種情況下。

當然,其他人也會遇到類似的情況。我希望有人「在那裏,做到了」可以分享一些智慧。 :-)

所以,這裏的問題是......在這種情況下,哪種方法應該是首選?爲什麼?有沒有更好的選擇,我沒有考慮?

回答

1

短短几意見/問題...

  • 如果不同位置的格式有沒有重疊的領域,什麼是他們的共性這將使他們對候選人的子類層次結構?你真的可以爲基類Location定義一個通用接口嗎?
  • TypeALocationTypeBLocation可比?
  • 是同一類型的SpecialItem中的兩個位置,還是可以混合使用?
  • 項目可以將其位置更改爲不同類型的運行時?

如上所述,值對象不能是多態的。根據你所描述的內容,我不明白你如何以多態的方式處理位置。

更新如果你不能確定你的位置類型的一個共同的基礎界面,這是非常尷尬的嘗試和對待他們多態,無論是否有ORM與否。以下面的例子爲例,即使訪問我居住的實際位置的任何信息,也需要將其下載到街道地址或經緯度座標。多態性意思就是爲了避免這種downcasts(並在類型字段上打開等)!

看選擇你上面描述,這一切考慮到:

  1. 就像你,我不喜歡它是(幾乎suprising)。
  2. 如果位置類型不是很多,可以成爲一個可行的選項,並且您可以合理確定您已經實現了所有需要的類型。在這種情況下,域類實際上是C類的一個類型字段。使用起來有點尷尬,但多態嘗試會更加尷尬恕我直言。
  3. 這絕對是一個有趣的想法,我可能會在一個寵物項目中嘗試一段時間,但我不太確定我想在我的生產代碼中使用這些技巧。我想也可以用一個自定義的映射類型來完成,它將映射你的組件到一個特定的子類。但是,我們再次嘗試將這些不兼容的類型放入類型層次結構中......嘗試這種方法的唯一好理由是,如果有許多位置類型和/或未來可能會出現新類型。
+0

通用性是兩個位置類型都滿足相同的需求。一個項目必須有一個位置,但是這個需求可以由任何一個子類型填充。 (請注意,位置超類型是抽象的。)擁有它們的實體會引用超類型以容納任何一個子類型。爲了比較,請考慮如何指定您居住的地方。您可以指定街道地址或緯度/經度組合。兩種格式都完成同樣的事情,但沒有共同的領域。 2個SpecialItem位置可以是不同的類型。 – MylesRip 2010-03-26 21:40:30

+0

我不相信多態處理價值對象時存在概念問題。它目前不受ORM支持。項目的位置可能會更改*值*。在領域模型中,這將通過用一個新的不可變的位置替換參考來完成(假設一個值對象方法)。在此應用程序中不支持在運行時將項目位置更改爲其他*類型*。 – MylesRip 2010-03-26 21:49:14

+0

授予位置中沒有太多行爲。 (我懷疑大多數值對象沒有太多的行爲,比如驗證,顯示,排序等等)我仍然需要一種方法來處理業務需求,也就是說實際上有多種位置格式,其中任何一種無論何時需要位置都是有效的。 鑑於上述情況,那麼您是否會實施選項2? ...或者完全不同的東西? – MylesRip 2010-03-26 22:53:49