2010-07-15 40 views
1

我們來看一個用於編輯客戶信息的UI示例。用戶編輯5個字段並按下「提交」。因爲我們是很好的抽象主義者,所以我們對5個領域進行了編輯,併爲他們制定了不同的命令(描述對特定領域的編輯)。什麼是命令處理程序和執行的事務邊界?

命令處理程序最終會對使用NHibernate等工具持久保存的對象設置屬性,因此我們最終將針對數據庫執行UPDATE。

我的主要問題是:從數據庫性能角度來看,發出單個UPDATE語句還是可以發出5個不同的UPDATE語句更合理?

我喜歡將命令處理程序作爲事務性邊界的想法。它可以工作並且事務被提交,或者它不會被執行,並且事務被回滾(並且我們可能重新排隊以再次嘗試)。每個命令的成功或失敗都是獨立於另一個的。

另一種方法可能是將這些命令的處理包裝到單個數據庫事務中,以便當NHibernate決定刷新它時最終發送一個UPDATE。但是,這使得處理命令成爲「全有或全無」類型的處理,我不一定非同步地執行它們。

但是,如果我想確保所有命令都正確執行,並且在發生故障的情況下完全回滾?也許有一個分佈式事務包含許多較小的事務?這可能導致數據庫爭用,增加死鎖的風險,這會減慢處理速度(進一步增加死鎖的風險)。但同時,一致性是關鍵。我想這是在可用性和一致性之間進行折衷(參見CAP)。

回答

4

從數據庫的角度來看,發佈單個更新幾乎總是更好 - 但是它取決於上下文是否真的重要。

但是,我不確定作爲一個「好抽象派」,當5個字段被編輯時,你真的想發出5個命令。您真正想要在DDD中執行的操作是針對用戶通過UI執行的每個邏輯操作發出單個命令。通常這只是每個操作一個,儘管對於更復雜的場景它可能不止一個。舉一個微不足道的例子,如果有人正在更新他們的地址,那麼你對每個字段都沒有一個命令 - 你有一個更新地址的命令。

您擁有的最小粒度級別是命令,因此命令處理程序中的任何內容都需要包含在事務中。我們所做的就是將命令放入一個工作單元,因此當我們發出多個命令時,它們全部通過或全部失敗。最後,我們提交事務,這意味着任何更改的對象(對於我們來說,它是聚合根加事件,因爲我們正在使用事件採購)得到堅持。如果你正在使用NHibernate來做到這一點,它可能會做一個操作 - 儘管當然這是由你持久性做的。

+0

我相信你對多個命令是正確的;針對單個邏輯操作發出命令,如「更新客戶的電話號碼」或「更新客戶名稱」(可能是多個字段)。 但是爲什麼每個命令都不是工作單位呢?例如,如果將這些命令發送到某個其他進程以異步執行,這可能是有意義的。 我們執行包含在一個事務中的命令,以從NHibernate管理多少個SQL語句的執行中受益。但是,由於這是全有或全無,我覺得它打破了命令的自然單元。 – 2010-07-17 01:02:31