2010-01-06 137 views
22

我們正在嘗試CQRS。我們有一個驗證情況,即CustomerService(域服務)需要知道客戶是否存在。客戶的電子郵件地址是唯一的。我們的客戶存儲庫(一個通用存儲庫)只有Get(id)和Add(客戶)。 CustomerService應該如何查明客戶是否存在?CQRS域名查詢

回答

23

看看這個博客帖子:Set based validation in the CQRS Architecture

它解決了這個非常問題。在CQRS中處理這個問題是一個複雜的問題。 Bjarte建議的是查詢報告數據庫中現有的客戶電子郵件地址,並在發現電子郵件地址時向域模型發回補償命令(例如CustomerEmailAddressIsNotUniqueCompensatingCommand)。然後,您可以發起適當的事件,其中可能包括UndoCustomerCreationEvent

通過對上述博客文章的替代思路的評論閱讀。

Adam D.建議中的評價是驗證域的關注。因此,您可以將ReservedEmailAddresses存儲在便於客戶創建的服務中,並通過事件存儲中的事件進行補充。

我不知道有一個簡單的解決這個問題,感覺完全乾淨。讓我知道你想出了什麼!

祝你好運!

+17

正如在其他答案中提到的,您不應該對您的視圖模型執行查詢作爲處理命令的一部分。如果有的話,這些查詢應該在發送命令之前由客戶端執行,並根據結果選擇不發送命令。 – 2010-06-27 18:42:27

+10

@Udi Dahan我不明白這是如何從SOA角度使用這個用戶名示例。當我收到CreateNewUserCommand時,當然需要檢查用戶名是否已經存在?我不能假設客戶已經完成了這項檢查,特別是如果客戶可能是第三方應用程序? 我理解處理命令時不執行查詢的基本原理,但我可以想到在處理命令時我需要分析命令要運行的聚合之外的數據的一些場景... – 2010-11-03 13:44:32

+11

第三方應用程序將通過一個行爲良好的「客戶端」進行連接,該客戶端可能是一個Web服務,並且它是對視圖模型進行檢查的一個,如果檢查通過,則將單向消息發送到「服務器」。 – 2010-11-04 19:11:44

5

這個問題並不一定是複雜的:

  1. 檢查客戶的獨特報表商店提交UpdateCustomer命令。
  2. 爲電子郵件地址的唯一性添加約束到您的數據庫。執行命令時,處理異常並使用回覆通道向用戶發送通知。 (hences從來沒有射擊CustomerUpdated事件報告店。

使用數據庫爲它的好,而且沒有獲得掛了ORM的限制。

+8

如果它不是數據庫怎麼辦 – andho 2011-07-17 17:55:36

+2

併發命令怎麼樣?可以在一些(罕見但可能的)情況下創建兩個客戶。 – 2017-01-28 17:48:40

5

本帖由烏迪大漢http://www.udidahan.com/2009/12/09/clarified-cqrs/包含以下段落:

「此外,我們不應該需要訪問查詢儲存處理命令 - 這是需要應該由獨立的組件來管理的任何狀態 - 這就是自治的意義的一部分。」

我相信Udi建議簡單地爲數據庫添加一個唯一的約束。

但是,如果你不想這樣做,根據上面的說法,我會建議只需將「ByEmail」方法添加到存儲庫並完成它 - 但是再次Udi可能會有一個更好的建議..

+3

儘管如此,這並不適用於所有情況,例如,我正在使用不支持「約束」概念的NoSQL數據庫。 – James 2014-05-01 15:08:25

+0

@james什麼nosql數據庫? – 2017-01-28 20:06:05

2

希望我不是太晚了......但我們在我們的項目中遇到類似的情況,我們實際上攔截命令執行與設定的該命令,又使用查詢創建的規則,將其固定獲取數據。

所以在這種情況下,我們可以通過名稱CustomerEmailMustBeUniqueRule來創建一個類,當RegisterCustomerCommandExecutor即將執行命令「RegisterCustomerCommand」時,該名稱由RuleEngine提取。此規則類有責任來查詢數據庫中查找,如果電子郵件ID存在,並通過提高無效標誌停止執行...

0
  1. 使用您的客戶表的ORM。 這樣一旦輸入重複密鑰,它將引發異常。 你應該使用DapperDotNet,它非常輕巧,易於使用。使用ORM的好處在於,它們中的大多數都允許您生成或創建類來代表數據庫中的現有表。它完全刪除了你必須去檢查現有記錄的數據庫的部分。

  2. 你也可以讓你的命令實現一個通過dataManager進行檢查的接口,但這不是必需的。

在大多數情況下,如果輸入了重複的鍵,你會想拋出一個異常。這也讓你有自由不必創建查詢來檢查存在。