- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个 API 应用程序,它使用多个数据库分片,并使用 StructureMap 进行依赖注入(inject)。每个 API 调用中的必需 header 之一是 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: Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur is you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
或其他异常表明 StructureMap 没有可用的 MyDbContext
的有效实例。
在我看来,多个线程似乎以某种方式弄乱了彼此的配置,但对于我的生活我无法理解,因为我正在使用嵌套容器来存储每个 API 调用的数据库上下文.
知道这里可能出了什么问题吗?
更新:我还尝试将我的 Db 上下文抽象到一个接口(interface)中。没有真正的区别;我仍然收到错误
System.InvalidOperationException: An error occurred when trying to create a controller of type 'SomeController'. Make sure that the controller has a parameterless public constructor. ---> StructureMap.StructureMapConfigurationException: No default Instance is registered and cannot be automatically determined for type 'MyNamespace.IMyDbContext'
更新 2: 我解决了问题,但赏金仍然开放。请在下面查看我的回答。
最佳答案
好吧...我解决了这个问题,但我不明白为什么这会产生影响。
它归结为与我最初发布的内容有一些细微的差异,我忽略了这些差异,因为我认为细节无关紧要并且会分散对问题的注意力。事实上,我的容器并不是在本地定义的;相反,它是我的中间件的 protected 属性(它是出于集成测试目的而继承的):
protected IContainer Container { get; private set; }
然后在Invoke()
方法内部有一个初始化调用:
Container = context.GetNestedContainer(); // gets the nested container created by a previous middleware class, using the context.Environment dictionary
在整个方法中使用日志记录语句,我得到了以下代码(如问题中所述,添加了日志记录):
_logger.Debug($"Line 1 Context={context.GetHashCode}, Container={Container.GetHashCode()}");
var db = MyDbContext.ForShard(shardKey.Value); // no need for "using", since DI will automatically dispose
_logger.Debug($"Line 2 Context={context.GetHashCode}, Container={Container.GetHashCode()}");
Container.Configure(cfg => cfg.For<MyDbContext>().Use(db));
await Next.Invoke(context);
令人惊讶的是,这是从日志中得出的结果:
Line 1 Context=56852305, Container=48376271
Line 1 Context=88275661, Container=85736099
Line 2 Context=56852305, Container=85736099
Line 2 Context=88275661, Container=85736099
太棒了!我的中间件的 Container
属性神奇地被替换了!这个,尽管它是用 private set
定义的,无论如何,为了安全起见,我检查了 MyDbContext.ForShard()
的代码并没有发现任何东西这可能会弄乱 Container
的引用。
那么解决方案是什么?我在初始化后立即声明了一个本地 container
变量,并使用了它。
它现在有效,但我不明白为什么或如何产生不同。
赏金将颁发给能够解释这一点的人。
关于c# - StructureMap 中的跨线程冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38775306/
http://docs.structuremap.net/似乎有使用已弃用成员的非常古老的示例。 有什么地方可以找到最新的 StructureMap doco 吗? 最佳答案 我似乎在以下位置找到了一
我似乎无法弄清楚如何将对象定义为单例并为构造函数定义两个参数。 我可以做/或 .. 只是不能同时做。 例如。 (这不起作用)... ForRequestedType() .TheDefault
有没有办法确定在 StructureMap 中是否配置了特定类型? 如果在 StructureMap 中没有专门配置,我想返回一个泛型类型。 最佳答案 在 v2.6 你想要: IContainer.M
我想配置结构图以使用工厂类创建服务。工厂本身有一个需要填充的依赖项。目前我的注册表类中有以下内容: For().Singleton().Use(() => new DoStuffWebServ
我正在尝试使用 StructureMap 2.6.1 使用基于约定的注册一次注册我的所有存储库。见下面的代码: x.Scan(s => { s.TheCallingAssembly();
在 StructureMap 中你可以声明一个 Forward声明,这将允许注册单个具体实例,以由来自 StructureMap documentation 的多个接口(interface)解析: v
在 StructureMap 2 中,我有这样的事情: For().HybridHttpOrThreadLocalScoped().Use(); 使用 Structure Map 3 时,我应该使用以
如何将 StructureMap 与 OpenRasta 一起使用?我可以使用它来代替内部依赖解析器,还是只能将它与内置 DI 结合使用(即用于我自己的应用程序的依赖项)? 谢谢 最佳答案 Struc
我刚刚开始使用 StructureMap,之前使用过 Spring.Net。我喜欢 DefaultConventionScanner 以及扫描程序集和使用约定优于配置来查找类的能力。但是似乎有一个限制
我有一个通用接口(interface) public interface IDomainDataRepository { T[] GetAll(); } 有一个通用的实现 public cla
我正在尝试从 Structuremap 2.6.4.1 迁移到 3.1.4.143,但无法弄清楚如何处理 HybridHttpOrThreadLocalScoped。我能找到的所有 SO Q/A 似乎
所以我有一种情况,我想注册 n 个特定查找类型的映射。即: x.For().Add(); x.For().Add(); 我想让 SM 将它们的可枚举(或数组)注入(inject)到类的构造函数中: p
以下哪种语法被认为是最佳实践? For().LifecycleIs(new HybridLifecycle()).Use(); For().LifecycleIs(Lifecycles.GetLife
StructureMap 有没有办法用一行或约定来做这种重复映射? For>().Use(); For>().Use(); For>().Use(); For>().U
似乎 NLog 不能对 GetCurrentClassLogger() 使用反射,即使我的 MVC 3 应用程序部署在 中完全信任 IIS7 环境。我使用的是 StructureMap 2.6.1,问
StructureMap 定义了一个接口(interface) IBootStrapper,我看到很多人在他们的 Bootstrap 类中实现了这个接口(interface)。 但是我找不到任何可以说
我们将 Caliburn.Micro 用于我们的 MVVM 框架,将 StructureMap 用于我们的 IoC 容器,并将 MediatR 用于我们的调解器实现。这一切都工作正常,除了注册 Med
使用方法DecorateAllWith用 DynamicProxy 装饰所有实例都实现了一个接口(interface)? 例如: public class ApplicationServiceInte
在 autoFac 中,我可以注册一个接口(interface)的多个实现。当 autofac 实例化我的对象时,所有实例都传递给构造函数。 来自 autofac 的文档:here For examp
我有一个 Repository 的基类。在一个特定的项目中,我有几个这个基类的实现。例如 PersonRepository : Repository EmployerRepository : Repo
我是一名优秀的程序员,十分优秀!