我得到了一个旧的 WinForms 应用程序来更新和改进。我正在尝试使用 SimpleInjector 添加 DI。我习惯了 .Net MVC,但这是我第一次使用 WinForms。
该应用程序使用了大量的 BackGround 工作者。我的理解是,这是特定于 WinForms 的,每个后台工作人员都会创建一个新线程。
我认为我的问题是,当我想使用 EF6 将数据保存到数据库时,由于多线程,SaveChanges 方法无法保存。
我的 SimpleInjector 容器设置如下
_container = new Container();
_container.Options.DefaultScopedLifestyle = new ThreadScopedLifestyle();
// Register DbContext
_container.Register<DbContext, MyDbContext>(Lifestyle.Scoped);
当我在 dbContext 上调用 SaveChanges 时,我得到的结果为 0,这表示没有记录保存到数据库中。在我的调试器中,我收到一条错误消息,指出 DbContext 已被处理。如果这发生在保存之前,它解释了为什么从 SaveChanges 返回 0。不幸的是,之前的开发人员捕获了每个异常,因此应用程序正在尝试处理每个错误,这使得故障排除变得困难并导致意外行为。
我期望为每个线程创建一个新的 DbContext,并且 SaveChanges 将保存在每个线程中所做的更改,以便在一个上下文中发生的事情不会影响其他线程中的其他 DbContext。
当我从数据库中读取数据时,我会在每个方法中手动创建一个新的 DbContext。当 using 块完成时,它是否可能正在处理 DbContext ?
using (var newDbContext = new MyDbContext())
{
return newDbContext.Set<TableA>().First(x => x.Id == id);
}
我希望如果我正确配置了 SimpleInjector,我也不需要这样做。
我在这个阶段有点迷茫,认为我可能没有正确理解文档,任何建议将不胜感激。提前致谢。
我期待为每个线程创建一个新的 DbContext
这不是TheadScopedLifestyle
工作方式。使用ThreadScopedLifestyle
,在显式启动的上下文中将有一个注册实例,Scope
并且此范围是特定于线程的。这意味着一个线程可以拥有该服务的多个实例,因为一个线程可以存活很长时间,而一个线程Scope
通常只能存活很短的时间。
的典型用途ThreadScopedLifestyle
如下:
void MethodThatRunsInABackGroundThread()
{
using (ThreadScopedLifestyle.BeginScope(container))
{
var service = container.GetInstance<ISomeService>();
service.DoWork();
}
}
当您解析Scoped
活动范围之外的实例(或某些包含范围实例的对象图)时,Simple Injector 将抛出异常。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句