2012-05-03 50 views
6

我喜歡Command Query Separation的想法,但無法看到如何在添加實體的MVC Controller操作中使用它,並且在添加它之後需要新實體的ID。在MVC控制器中使用命令查詢分離原理

例如,在服務下面的簡單的例子來創建一個新項目:

public ActionResult Assign(AssignViewModel viewModel) 
{ 
    var newItem = _AssignItemService.AssignItem(viewModel.ItemName, viewModel.ItemValue); 

    return RedirectToAction("ListItem", new {id = newItem.Id); 
} 

但是,當我重定向到這是會顯示新項目的動作,我需要知道新創建的項目的ID,以便它可以從數據庫中檢索。所以我必須要求服務返回新創建的項目(或者至少是它的ID)。

在純CQS中,一個命令沒有返回值,所以上面的模式將是無效的。

任何建議感激地收到。

回答

4

你應該傳遞給AssignItem方法一個「Item」(或者你的實體的名字)的實例,它是從viewmodel的值創建的,那麼這個方法不需要返回任何東西,它只會更新實體的Id屬性它是一個Command方法。

然後可以使用entity.Id爲任何你想要的

+0

以後如何檢索「item」? –

+0

傳遞給AssignItem方法的對象返回後會包含Id信息。由於該方法是一個命令,所以可以改變對象的狀態 – jorgehmv

+0

你不是基本上還在那個時候返回一個值嗎?當然,它不是從函數的後面出來的,但是你仍然返回一個值,你只是將返回值推到別的地方。也就是說,我喜歡將ID保留在對象內的想法,而不是單獨返回。 –

8

我認爲你被困在一個迂腐點。

查詢是當你想問一個數據庫的問題,如「密西西比以西有多少客戶在6月份購買了紅色的物品?」這是一個查詢。在插入過程中返回ID本身不是典型的查詢。

與軟件開發中的大多數其他事情一樣,此模式絕對不是即使福勒說,他願意打破它時,它是方便這樣做:

跳跳堆棧是修改狀態的修改的一個很好的例子。邁爾正確地說,你可以避免使用這種方法,但它是 一個有用的習慣用法。所以我更願意遵循這個原則,但我可以,但 我準備打破它,讓我的流行。

如果您確實想從數據庫中檢索最近添加的ID,那麼您可以使用類似Scope Identity之類的東西。但我認爲你增加了複雜性,沒有額外的好處。

+0

此外,請確保您使用Scope身份或類似的,以正確處理多線程情況。例如'T1'插入,'T2'插入,'T1'從'T2'插入中獲得'Id','T2'獲得相同的Id。當然,同樣的問題適用於任何原子操作/交易,所以我相信你已經考慮過這個問題。 – Basic

+0

讓數據庫通過插入函數的返回值爲您提供ID的另一個好理由。 –

+0

我認爲Fowler的評論考慮到堆棧中的pop方法是好的,因爲它的使用是一般的,所以它已經成爲所有開發人員的成語,但我不認爲從保存方法返回id是一個習慣用法。我同意你的觀點,儘管沒有什麼是絕對的,在短時間內打破這種規則並不是什麼大事 – jorgehmv

0

的方式做到這一點是使主叫方指定新的實體(這很可能意味着使用的GUID爲重點)的ID。

但是,根據我的經驗,強加一條命令可能不會返回結果的(純粹的)規則會導致問題,但收效甚微。

+0

謝謝erikkallen。有道理,但最終我認爲jorgehmv的想法對我來說會更好。 – Appetere