我有一個使用多個數據庫分片的API應用程序,使用StructureMap進行依賴注入。每個API調用中所需的標題之一是ShardKey
,它告訴我此調用正在尋址哪個數據庫。爲了實現這一點,我有一個OwinMiddleware
類稱爲ShardingMiddleware
,其中包含下面的代碼(剪斷爲清楚起見):StructureMap中的跨線程衝突
var nestedContainer = container.GetNestedContainer();
using (var db = MyDbContext.ForShard(shardKey)) // creates a new MyDbContext with connection string appropriate to shardKey
{
nestedContainer.Configure(cfg => cfg.For<MyDbContext>().Use(db));
await Next.Invoke(context);
}
這精美的作品在我的測試環境,並通過集成測試的電池。
但是集成測試實際上是單線程的。當我將這部署到一個QA環境中時,一個真正的應用程序通過多個同時調用在我的API中觸發,事情開始變成梨形。 Ferinstance:
System.ObjectDisposedException:無法訪問處置的對象。造成這種錯誤的一個常見原因是處理從依賴注入解決的上下文,然後嘗試在應用程序的其他地方使用相同的上下文實例。這可能發生在你正在上下文中調用Dispose()或將上下文包裝在using語句中。如果您正在使用依賴注入,則應該讓依賴注入容器負責處理上下文實例。
或其他異常指示StructureMap沒有可用的MyDbContext
的有效實例。
對我來說,似乎多線程在某種程度上搞亂了彼此的配置,但對於我的生活我無法理解,因爲我使用嵌套容器來存儲每個API的數據庫上下文呼叫。
任何想法可能會在這裏出錯?
更新:我也嘗試將我的Db上下文抽象爲接口。沒有真正的區別;我仍然收到錯誤
System.InvalidOperationException:嘗試創建類型爲'SomeController'的控制器時發生錯誤。確保控制器有一個無參數的公共構造函數。 ---> StructureMap.StructureMapConfigurationException:沒有默認實例被註冊,並且不能爲類型「MyNamespace.IMyDbContext」
更新2自動確定:我解決了這個問題,但獎金仍然是開放的。請參閱下面的答案。
您的'DbContext'可能會作爲[Captive Dependency]保留下來(http://blog.ploeh.dk/2014/06/02/captive-dependency/)。確保此依賴項的使用者的生命週期的壽命不超過'DbContext'的壽命,或者 - 甚至更好 - 防止將DbContext直接注入到消費者中。 'DbContext'是運行時數據,運行時數據[不應該注入到組件中](https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=99)。而是在抽象背後隱藏DbContext。 – Steven