2011-03-01 46 views
1

我有一個自定義ASP.NET成員資格提供程序,我試圖添加密碼歷史記錄功能。用戶密碼在X天后過期。然後他們必須將他們的密碼更改爲以前的X更改中未使用的密碼。是否應該始終加載域實體?

我已經擁有了用戶實體,它擁有當前密碼的密碼屬性。這映射到數據庫中的用戶表。因爲我需要一個以前的密碼列表,所以我創建了一個UserPassword表來存儲這個信息,其中包含了對UserId的FK引用。

由於密碼是值對象,並且在用戶之外沒有任何意義,所以它們屬於User聚合內部,並且以User作爲根。但在這裏謊言我的困境。當我從存儲庫中檢索用戶時,是否總是必須獲取他們以前使用過的所有密碼? 99%的時間我不關心他們的舊密碼,所以每次我需要一個用戶實體時檢索它們看起來像是一個愚蠢的事情來做數據庫性能。我不能使用延遲加載,因爲用戶實體與上下文斷開連接。

我想創建一個PasswordHistory實體,但由於上述原因,密碼並不是真正的實體。

DDD專家如何處理這種情況?

謝謝。

編輯1:考慮到這一點之後,我意識到這實際上是一個關於延遲加載的問題。更具體地說,你如何處理一個斷開的實體中的延遲加載?

編輯2:我正在使用LINQ to SQL。使用CodePlex的this將實體完全脫離上下文。

回答

0

很難完全回答這個問題,因爲你沒有指定一個平臺,所以我不能完全確定你甚至是什麼意思的「斷開」。 Hibernate「斷開連接」意味着你在有效會話中有一個對象,但是數據庫連接當前沒有打開。這是微不足道的,你只需重新連接和延遲加載。更復雜的情況是,你有一個「分離」的對象,即根本不再與活動會話相關聯,在這種情況下,你不能簡單地重新連接,你必須得到一個新對象或附加一個你需要的對象活動會話。無論哪種方式,即使在更復雜的情況下,延遲加載策略仍然沒有太多,因爲需求非常不靈活:您必須「連接」才能加載任何內容,懶散或其他方式。期。我會認爲「斷開」意味着與分離相同的事物。您的策略歸結爲兩種基本情況:這是一種情況,您可能需要重新連接/隨時附加到延遲加載,或者您是否想要在斷開連接之前有時有條件地加載其他對象的情況下首先?

有時你可能實際上需要爲兩種可能性編碼。

在你的情況下,你不僅需要連接到懶加載舊密碼,而且要首先更新用戶對象。此外,因爲這是ASP.NET,您可能會使用每個請求的會話,在這種情況下,您的選項現在基本上只能達到一個 - 在斷開連接之前有條件地延遲加載,這就是它。

最常見的情況是人員登錄,系統確定他們需要更改密碼,並在繼續之前要求他們這樣做。在這種情況下,您可能只需在登錄後立即處理它並保持用戶連接。但是您可能使用每個請求的會話,所以您可以在第一個請求過程中執行時間限制,如果過期,您仍然連接到此處,然後返回完全加載的用戶(假設您使用的是歷史記錄某些客戶端腳本驗證中的密碼)。然後在提交旅程中,您可以重新附加或僅獲取新的用戶實例並更新該實例。

然後,您總是有可能隨時爲他們提供更改密碼的選項。他們已經登錄。這裏沒什麼關係,你有一個用戶,但是請求早已結束,並且沒有加載密碼。在這裏,我可能會寫一個服務方法,當他們調用一個更改密碼函數時,服務會獲取具有完整歷史記錄的User對象的第二個副本,僅用於更新目的,然後更新密碼,然後丟棄該對象將其用於會話或身份驗證目的。或者,如果您使用每個請求的Session,則必須執行相同的操作 - 爲客戶端驗證目的獲取完全初始化的對象,然後在提交數據時,您可以重新附加已有的任何一個或只需獲得第三個實例做更新。

如果在開始認證會話後需要密碼,您仍然可以執行相同的操作,並替換本地用戶或更新本地用戶的內存密碼版本。

如果你有太多的事情正在進行多級別的認證,很可能你將不得不要求他們註銷並在密碼更改後進行完整的重新登錄,所以用戶的狀態不會一旦他們要求更改密碼,他們就很重要。

在任何情況下,如果您對每個請求使用會話,並且每次請求後對象變爲完全分離,則在第一種情況下,您仍然可以在原始請求上的服務器上進行延遲加載,以便爲客戶端驗證返回數據。在第二種情況下,你必須再次旅行(這裏真的沒有懶惰加載這樣的事情)。在這兩種情況下,儘管您必須權衡兩個更新選項,因爲在更新之前您總是斷開連接。您可以在提交旅程中從數據庫獲取第二個實例進行更新,也可以重新附加已有的實例。它取決於什麼是最優/最簡單的 - 爲非常見事件保存數據庫往返真的很重要嗎?無論如何,使用您選擇的ORM進行重新連接可能會再次觸及數據庫嗎?我可能不打算重新附加,而只是根據需要爲實際更新獲取新實例。

+0

我正在使用LINQ to SQL,並使用CodePlex中的[this](http://linq2sqleb.codeplex.com/)從上下文中完全分離實體。這個項目中的其他實體會執行對象關聯的條件加載,結果是一個完整的噩夢。我不知道這種模式有多頻繁,但從現在開始我會避開它。所以...不情願那個解決方案,我選擇刪除用戶的關聯,並創建一個PasswordHistory域實體,以包含UserPassword數據庫實體和相關邏輯的列表。我必要時使用這個實體做一個單獨的請求。 – mikesigs 2011-03-02 15:36:18

相關問題