2014-10-18 62 views
1

我正在開發使用ASP.NET MVC的基於Web的應用程序。我想要擁有豐富的域模型,而不是瘦/貧血模型。是否可以在我的域模型中使用數據庫上下文

我已經模擬了我的解決方案,沿着洋蔥架構的線條。不同的項目是如下: enter image description here

  • {} .Domain.Core - 包含其在基礎設施層
  • {} .Database實現的域對象和接口等IDbContext - 是數據庫prject
  • {]。基礎設施 - 包括實施記錄,數據訪問等
  • {}名.web - 視圖和控制器

****的數據訪問使用dapper完成,IDbContext是2個簡單的命令查詢接口的封裝。我已將每個查詢分隔爲單獨的類。

爲了討論的緣故,我正在申請一小部分應用程序。

我有一個版本的文檔庫中包含的文件中包含的標籤其他元數據,權限等

是如下圖所示

enter image description here

我的文檔對象的簡化模型我想的要在域對象中定義操作,因爲每個操作都涉及業務邏輯。 讓我把「刪除」作爲一個操作。操作必須執行

  • 驗證,如果用戶有權限刪除
  • 檢查是否有任何關聯,將通過此獲得的影響刪除
  • 檢查,如果沒有工作流過程中
  • 刪除在交易中來自數據庫的實際項目

如上例所示,我需要數據庫上下文來完成此操作。 我現在的想法是,如果建模是讓域對象具有IDbContext,它可以執行查詢公開。

enter image description here

在我的控制器類我所謂的域對象,並執行操作。

我不確定在域對象中傳遞IDbContext是否正常?如果沒有什麼更好的方法來模擬這個?

我不相信在具有一個單獨的服務層,因爲 1)控制器充當用於大多數情況下 2)服務層只是重複從域相同的方法,以另一級的服務層的第一層

讓我知道如何讓這個設計更好。

回答

2

注入IDbContext就像制動了域模型的主要原則,應該只負責業務邏輯,同時檢索和存儲您的域實體是基礎設施層的責任。是的,你通過接口注入它,隱藏實際的實現,但它使你的域模型知道一些存儲。

另外,從上面的步驟需要刪除Document並不屬於Document對象。讓我們考慮與用戶權限和下列情況下的第一步:

  • 用戶具有管理員的角色應該被允許刪除任何文件
  • 文檔所有者應允許刪除文檔

對於第一種情況可能沒有用戶和要刪除的文檔之間的連接。管理員用戶只能執行任何操作。這就像一個經典的例子,有兩個銀行賬戶和一個轉賬操作,涉及兩個賬戶但不是他們的責任。這是域服務到位的時候。請不要將它們與服務層服務混淆。域服務是域模型的一部分,僅負責業務邏輯。

因此,如果我是你,我會用DeleteDocument方法創建一個新的域服務。這應該從接受UserDocument作爲參數的前三個步驟完成。第四步應該由您的存儲庫完成。不知道你說

我沒有看到太多的價值添加軟件庫

但是從域模型的角度是什麼意思,你已經有一個它的IDbContext。我假設你的意思是爲每個實體實施知識庫或單獨的知識庫。在漫長的控制器運行的僞代碼應爲以下:

var user = bdContext<User>.SelectById(userId); 
var document = bdContext<Document>.SelectById(docId); 
var docService = new DocumentService(); 
docService.DeleteDocument(document, user); // Throw exception here if deletion is not allowed 
bdContext<Document>.Delete(document); 

如果你期望你需要這個邏輯在你的應用程序的許多地方,你可以把它包裝起來的一個服務層服務。

如果你想了解更多關於領域建模的知識,我建議你閱讀埃裏克埃文斯book的DDD。這將詳細討論實體,值對象,域服務等的含義。

回答: 不是,域服務是域的一部分,所以實現和接口都是域的一部分。兩個或多個對象必須相互交互的事實不足以創建域服務。以航班預訂系統爲例。您有一個具有不同屬性的Flight實體,如DepartureCityArrivalCityFlight實體也應該提供一個座位列表。 (商業,經濟等),Type(島,行,中等)等等。因此,預訂座位需要與不同實體相互作用,例如FlightSeat,但是也可以是FlightSeat。我們在這裏不需要域名服務。性質Seat如果不被視爲Flight的子對象,則屬性沒有意義。甚至不太可能會有這樣一種情況,即從Flight上下文中查詢Seat實體。因此保留SeatFlight實體的責任,並且可以將預留邏輯放置到Flight類。請注意,這只是一個例子,可以嘗試解釋何時需要創建域服務,真正的系統可以完全以另一種方式建模。所以,只是嘗試以下三個基本步驟來決定你是否需要一個域名服務:

  1. 由服務執行的操作是指不自然屬於一個實體或值對象的域概念。
  2. 執行的操作是指域中的其他對象。
  3. 該操作是無狀態的。

我是從控制器,其應用/服務層不域/業務層訪問的DbContext。域模型只處理業務邏輯,它不應該知道任何持久性邏輯,並且從上面的示例中可以看到DocumentService沒有引用dbcontext。

+0

感謝您的詳細回覆。根據我的理解,您正在創建一個域服務,其中一個或多個域對象需要進行交互(在大多數情況下都是如此)。在此圖層中,您正在訪問dbcontext。那麼核心領域是否意識到了域服務的接口,但實際的實現是在外部的呢?因此,我的控制器仍然與域和對象進行交互,與域服務進行交互以執行任何操作。我的理解是否正確? – 2014-10-19 18:57:56

+0

@Sharath Chandra更新了我的答案和更多信息。 – 2014-10-19 22:14:28

+0

感謝您瞭解我對域服務和應用程序服務的理解。在附註中,我曾嘗試過埃裏克埃文斯的DDD,但因爲感覺太乾燥而放棄了。但是,通過一些實際的工作,讓我再試一次。 – 2014-10-20 04:22:35

相關問題