7

我很努力地理解如何最好地查詢存儲庫。儲存庫和查詢與原始的SQL?

這三個因素都扔我通過一個循環,現在是:數據

  1. 返回類型
  2. 列上運行
  3. 的記錄數查詢返回

點1

關於任務離子之一:

我有許多方法,返回實體和標量值的組合方法的存儲庫。這似乎導致「方法爆炸」。我應該總是返回一個實體對象嗎?我應該如何查詢只需要一列的對象?

點2 當運行一個查詢我應該包括在,即使我只需要一個或兩個列的表的每一列?如果我爲此創建特定查詢,則會導致更多方法存儲庫中

點3 我該如何爲查詢提供條件?我閱讀了關於規格的內容,但我的理解是,您循環返回的記錄並過濾掉傳入新集合的記錄。這似乎不是一個好主意性能明智的。現在我只是在Repo中創建一個新的方法,例如getNameById()來封裝條件。

請不要說我沒有使用ORM,我只是在我的存儲庫的原始sql。

更新

點1: 基於答案,多一點研究這會是一個很好的執行?

現在,我有一個大的存儲庫,它返回標量和實體類型對象(所有相同的實體)的混合。我想如果我只是使用GetUser(userId)方法並忘記編寫只返回單列值的方法,我可以大大減少這個問題。

例如,如果我需要返回一個用戶名,我可以調用GetUser(userId)方法來保存用戶對象,然後在服務層中將其過濾爲用戶名。

另一種方法是使用某種QueryBuilder類,我可以將其傳遞到Repository中,這個類可以被解析以生成正確的SQL。

點2

回首這是非常相似點之一,我目前的解決辦法是隻獲取所有表字段。這是性能和可維護性之間的折衷。

3點

我需要提供某種形式的where子句中。我不確定這是否合理,通過規範或只是一個SQL字符串。我目前的解決方案是爲這些類型創建新的方法,但我希望更通用的存儲庫

總的來說,仍在研究這個...我很想聽到更多的輸入或鏈接到書籍或參考那種把這一切聯繫在一起。

+0

您是否在類中動態創建Sql命令? – Arian 2012-02-27 20:43:16

+0

原始SQL和沒有ORM,哈?就像生活在邊緣,是嗎?說真的,你爲什麼要處理原始的SQL? – 2012-02-27 21:12:02

+0

@ yves - 寶貝步驟:) – chobo 2012-02-27 21:29:10

回答

3

我有很多方法返回實體和標量值的組合方法的存儲庫。這似乎導致「方法爆炸」。我應該總是返回一個實體對象嗎?我應該如何查詢只需要一列的對象?

您可以打開存儲庫方法爆炸,類似於打擊其他SRP違規行爲。您可以爲同一個實體創建另一個存儲庫。看到這個answer類似的問題。

當運行一個查詢時,我應該包括表中的每一列,即使我只需要一列或兩列?如果我爲此創建了特定查詢,它會導致更多方法在存儲庫中

這不是DDD問題。 域名驅動設計不處理'行和列'。在加載「水合」域對象的數據量方面總會存在一些冗餘,但您必須測量這是否會影響您的性能。如果這實際上是一個性能瓶頸,那可能是一個不正確的域模型的症狀。

我該如何爲查詢提供條件?我閱讀了關於規格的內容,但我的理解是,您循環返回的記錄並過濾掉傳入新集合的記錄。這似乎不是一個好主意性能明智的。現在我只是在Repo中創建一個新的方法,例如getNameById()來封裝條件。

這又是一個數據訪問問題。 DDD中沒有任何內容表示您的存儲庫無法將規範轉換爲SQL查詢。無論您是執行此操作還是遍歷內存中的記錄(只要存儲庫使用者只能看到規範和存儲庫並且不知道實際實現),由您決定。

關於'原始SQL與DDD中的ORM',你可能會發現這個answer有趣。

+0

你能指出一些解決這個數據訪問問題的答案或教程嗎? – chobo 2012-02-27 22:51:49

+0

由於性能方面的考慮,DDD本身有一個關於規範的例子,它被轉換爲原始SQL。 – Dmitry 2012-02-27 22:57:19

+0

埃裏克埃文斯是藍色的嗎?不會知道該例子的頁碼?:) – chobo 2012-02-28 00:50:38

1

首先,你還沒有真正解釋你正在使用所有這些查詢。很有可能是用戶界面的需求。如果是這樣,則不需要跳過所有這些環節(service-> repository-> domain-> dto-> client),只需儘可能直接查詢數據庫即可。而你知道些什麼,不管你是否可以查詢標量或僅僅是你需要的列,都是問題。只需使用普通的sql並返回你所需要的。不要造成造成摩擦的抽象。

+0

我所需要的是一個「最佳實踐」的方法來查詢存儲庫,所以我沒有一百萬個方法,它以某種方式在一些體面的表現以及。 – chobo 2012-02-27 22:54:29

+0

如果它們沒有達到域的目的,首先不要將它們添加到存儲庫中。將它們移動到另一個表示用戶界面所需查詢的外觀。從客戶端到門面,從數據庫到客戶端,都要儘可能快地完成。使用簡單的DTO來表示需要傳送給客戶的狀態。 – 2012-02-28 16:15:54

2

我同意德米特里所說的一切,但也許認爲你應該讀一讀CQRS

當我開始使用DDD時,我曾經問過類似的問題(關於'方法爆炸',而不是你的SQL問題),這導致我到CQRS。就個人而言,如果沒有它,我真的不知道DDD是如何實用的,並且它在查詢數據時回答了很多這樣的問題。使用它的原則我建議是:

  1. 只在提交事務時使用域存儲庫。也就是說,您不要使用存儲庫在UI中顯示數據。只有在您想對它們執行操作時,才能從存儲庫中獲取聚合。
  2. 您的存儲庫僅返回聚合,而不是單獨的實體。這是有道理的,因爲我們只是在事務意義上使用存儲庫,並且實體只能通過原子操作進行變異,並作爲一個整體持久化。
  3. 您可以創建單獨的存儲庫(或「查詢服務」),爲您需要的任何數據提供量身定製的查詢和數據類型。這些可以返回沒有邏輯的啞DTO。

這使您的本地域&庫保持清潔,同時提供創建提供高性能查詢的精簡數據訪問層的方法。

關於規範模式:而不是將其轉換爲代碼中的SQL查詢,您可以在規範中提供代表條件的公共屬性。然後可以將這些值添加到SQL的where子句中,或作爲參數發送到SPROC。

1

Chobo,

我們需要記住庫[福勒POEAA] [埃文斯DDD]模式中的兩件事情:

  1. 使用存儲庫模式作爲一個簡單的集合。存儲庫抽象這些基礎結構的細節,因爲不是來自域。
  2. 如果存儲庫pattren是一個集合,它是一組相同類型的對象。

其他兩種類型可能會幫助您的知識庫:查詢對象[Fowler PoEAA]和數據映射器[Fowler PoEAA]模式。查詢對象模式使用面向對象方法的聚合準則,並知道如何將它們轉換爲SQL語句。數據映射器模式知道映射應用程序中的對象狀態和數據庫中的表列。

您可以使用Lazy Load模式[Fowler PoEAA]來減輕內存中大對象的問題。

成功爲您服務!

+0

我認爲查詢對象將有助於很多與查詢不同的標準問題。我猜ORM的內置了這個功能。感謝解決這些問題的模式列表! – chobo 2012-02-29 23:20:05