【发布时间】:2016-08-04 18:56:34
【问题描述】:
我有一个使用多个数据库分片的 API 应用程序,并使用 StructureMap 进行依赖注入。每个 API 调用中所需的标头之一是 ShardKey,它告诉我此调用正在寻址哪个数据库。为了实现这一点,我有一个名为 ShardingMiddleware 的 OwinMiddleware 类,其中包含以下代码(为清晰起见,已截断):
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,事情开始呈梨形。费伦斯登:
System.ObjectDisposedException:无法访问已处置的对象。此错误的一个常见原因是释放从依赖注入中解析的上下文,然后尝试在应用程序的其他地方使用相同的上下文实例。如果您在上下文上调用 Dispose() 或将上下文包装在 using 语句中,则可能会发生这种情况。如果你使用依赖注入,你应该让依赖注入容器负责处理上下文实例。
或其他异常表明 StructureMap 没有可用的MyDbContext 的有效实例。
在我看来,多个线程似乎在某种程度上弄乱了彼此的配置,但对于我来说,我无法理解如何,因为我正在使用嵌套容器来存储每个 API 调用的数据库上下文.
有什么想法可能会出错吗?
更新:我还尝试将我的 Db 上下文抽象为一个接口。没有真正的区别;我仍然收到错误
System.InvalidOperationException:尝试创建“SomeController”类型的控制器时发生错误。确保控制器有一个无参数的公共构造函数。 ---> StructureMap.StructureMapConfigurationException:没有注册默认实例,无法自动确定类型'MyNamespace.IMyDbContext'
更新 2:我解决了问题,但赏金仍然开放。请看下面我的回答。
【问题讨论】:
-
您的
DbContext可能作为Captive Dependency 保持活跃。确保此依赖项的消费者的生命周期不超过DbContext的生命周期,或者 - 甚至更好 - 防止将 DbContext 直接注入消费者。DbContext是运行时数据,运行时数据should not be injected into components。而是将 DbContext 隐藏在抽象后面。
标签: c# asp.net multithreading structuremap