2013-01-21 42 views
2

我們使用NServiceBus和Ninject來實現多租戶SaaS應用程序。NServiceBus和Ninject - 訪問NSB消息屬性

當用戶訪問我們的網站或API時,我們可以通過檢查HttpContext請求對象的主機名來確定用戶連接到哪個帳戶,檢索有關帳戶的各種設置(其中之一是我們應該使用的數據庫連接到),其餘請求連接到正確的數據庫(進行各種其他檢查)。

在我們的NSB Windows服務,我們沒有一個共享的情況下,使我們能夠確定主機數據庫連接的那個概念,所以我們創建存放帳戶/數據庫對我們的基本命令類的屬性誰創建了命令/消息。

當爲傳入消息構造消息處理程序時,其中一個依賴項是一個存儲庫,該存儲庫將它應該連接到的數據庫的名稱作爲參數。

正如之前所說,Ninject能夠訪問正確的數據庫中的HttpContext Web請求,但爲NSB服務本身包含我們只能在處理後接入構造,這顯然失敗了DB細節的消息,因爲它需要一個參數(包含在消息中!)成功構建存儲庫。雞和蛋:)

這是問的長篇大論方式...

  • 反正是有在Ninject創建週期內訪問消息的屬性?
  • 這感覺就像是那些難以解決的難題之一,因爲我的架構「錯誤」,是這樣嗎?
  • 我想避免在「SetDatabase」這樣的資源庫上放置公共屬性,因爲這樣可能會很容易被濫用/誤解並導致用戶數據混亂。
  • 我也想過創建一個存儲庫工廠,Ninject會使用但仍不知道如何訪問傳入消息屬性。

在此先感謝!


編輯爲解決

我結束了使用從烏迪和埃本答案的混合方法。

我對我的API消息使用了出去消息增發器,它將客戶的賬戶名添加到出站消息的頭文件(來自HttpContext)。 然後,在NSB Windows服務中,我使用一個入站增強器來檢查標題並提取帳戶名稱,如Udi所示。

我還創建了一個接口的實例,該接口爲Eben提供的連接字符串/帳戶詳細信息提供給我的存儲庫。一個用於web請求,一個ThreadStatic類型由傳入的mutator設置,然後Ninject綁定用於NSB的repo實例化。

我不能標記既是正確的,對不起埃本!:)

+0

我有一個類似的架構,以及類似的問題。你是如何配置你的容器註冊以從入站消息變更器中獲取租戶的?你能分享一些代碼嗎? – Junto

回答

0

你應該看看利用工作或消息突變掛鉤的單位做那種工作。這裏更多的信息:

http://support.nservicebus.com/customer/portal/articles/860275-unit-of-work-in-nservicebus

http://support.nservicebus.com/customer/portal/articles/860492-pipeline-management-using-message-mutators

我也建議使用您的郵件標頭之類的信息,而不是把它放在一個基類。

+0

感謝烏迪,是因爲帳戶信息的標題建議。是關於連接的元數據? –

+0

會一個傳送消息的Mutator是適合於正確的帳戶名稱添加到出站消息和工作單元開始()被用於檢查入站消息頭的方法? –

0

你肯定似乎有一點的架構問題。

要變通解決此問題,可能需要一個ITenantProvider,它由HttpTenantProviderThreadStaticTenantProvider執行。爲你的網站,你可以注入HTTP版本到存儲庫,它會問,比如說,TenantProvider.DatabaseName實例(或任何你需要的)。對於端點實現,您可以使用'線程靜態'實現。我只是說線程靜態,因爲您將要從多個線程訪問租戶提供程序實例,並且可能需要線程特定的狀態。但是,你決定這樣做取決於你:)

在你的消息處理開始時,你可以投射到線程靜態版本,並沿着((TheadStaticTenantProvider)TenantProvider).SetCurrentMessage(theMessage)行調用某些東西。然後,存儲庫將通過消息的線程靜態租戶提供程序接收所需的數據。

Shuttle我們使用處理管道,所以我會創建一個模塊插入到處理接收到的消息的管道中,以便爲我在租戶提供商上設置消息。我不知道NServiceBus不夠好,但有可能是類似的東西在那裏收到消息後,設置此爲你,你可以掛接到一個事件。

我希望我是有道理的:)

+0

謝謝,我實際使用這樣的一個模型連接字符串,我不知道爲什麼我沒有想到來擴展... :) 爲了澄清,你的建議是,每一個消息處理程序將不得不調用方法,設置當前消息能夠訪問主機名?大概在一個基類或一些這樣的? –