2009-09-14 46 views
1

我期待看到人們可能採取了哪些方法來檢測屬於其聚合的一部分的實體中的更改。我有一些工作,但我並不是瘋了。基本上,我的倉庫負責確定聚合根的狀態是否已更改。假設我的聚合根中有一個名爲Book的聚合根和一個名爲Page的實體。 A Book包含一個或多個Page實體,存儲在Pages集合中。檢測聚合根目錄中實體的更改

首先,插入與更新方案是通過檢查聚合根和它的實體來確定密鑰的存在來完成的。如果鍵存在,則假定該對象一次被保存到基礎數據源。這使得它成爲更新的候選者;但它不是基於單獨的實體而確定的。對於聚合根來說,答案是顯而易見的,因爲只有一個,並且它是單一的入口點,所以可以假設關鍵存在將決定操作。在我的情況下,可以接受的方案是再次保存聚合根本身,以便我可以捕獲修改日期。

爲了便於實體本身的這種行爲,我的EntityBase類包含兩個簡單屬性:IsUpdated(),IsDeleted()。這兩個都默認爲false。如前所述,我不需要知道它是否是新的,因爲我可以根據密鑰的存在做出決定。實現方法(在本例中爲Page)將使每種方法將後備數據集IsUpdated()更改爲true。

因此,例如,Page有一個名爲UpdateSectionName()的方法,該方法更改SectionName屬性的後備值,該屬性是隻讀的。這種方法一直使用,因爲它允許執行該數據設置的方法中驗證器的邏輯連接點(防止實體進入無效狀態)。最終的結果是我必須在該方法的末尾添加this.IsUpdated() = true;

當聚合根被髮送到存儲庫的Save()(一個邏輯開關進行控制,一個Insert()Update()操作)時,它可以然後遍歷Pages集合中的Book,尋找具有一個三者的任何頁方案:

  1. 沒有鑰匙。沒有密鑰的Page將被插入。
  2. IsDeleted = true;刪除勝過更新,並且刪除將被提交 - 忽略Page的任何更新。
  3. IsUpdated = true;頁面會提交更新。

這樣做可以防止我盲目更新Pages集合中的所有內容,例如,如果書中有幾百個Page實體,那麼這可能令人望而生畏。我一直在考慮檢索本書的副本,並進行比較,只檢查變化(根據狀態和/或比較插入,更新和刪除),但這似乎是一種非常好用的方法。

主要缺點是開發人員必須記住在實體中的每個方法中設置IsUpdated。忘記一個,它將無法檢測到該值的變化。我已經提出了某種自定義後備存儲的想法,它可以透明地對變更進行時間戳記記錄,這又可以使IsUpdated成爲存儲庫可用於聚合更新的只讀屬性。

存儲庫正在使用工作單元模式實現,該工作模式實現基於其聚合根添加到其時的時間戳上的操作。由於可能有多個實體排隊等待操作,因此實體操作將在實體所屬的集合根操作執行後立即彙總並執行。我可以看到更進一步,創建另一個工作單元來處理實體操作,並將它們從實體中使用的某種事件跟蹤中剝離出來(這就是我如何假設市場上的一些ORM產品完成了類似的功能級別)。

在我繼續朝着這個方向前進的過程中,我很想聽到關於這方面的想法/建議/經驗。

編輯:一些額外的信息,可能有助於瞭解:

  1. ,我有工作當前語言是C#,雖然我試圖保持儘可能多的特定語言信息進行儘可能,因爲這更多是理論上的討論。
  2. 存儲庫/服務/實體/等的代碼。基於Tim McCarthy的概念,在他的書「.NET域驅動設計與C#」和支持代碼CodePlex。它提供了對所採取的方法類型的可運行理解,儘管我所從事的工作基本上已從頭改寫。

回答

1

總之,我的答案是我用我的建議去。它正在工作,但我確信還有改進的空間。這些變化實際上花費的時間很少,所以我覺得在這種情況下我沒有離開KISS或YAGNI校長太遠。 :-)

我仍然覺得在操作上有與時間有關的問題,但我應該可以在存儲庫實現中解決它們。不是最理想的解決方案,但我不確定是否值得重新發明解決問題的方法,可以在比解決問題所需的時間更短的時間內解決問題。