ASP.NET Core 新建线程中使用依赖注入的问题
问题来自博问的一个提问 .net core 多线程数据保存的时候DbContext被释放 。
TCPService 通过构造函数注入了 ContentService , ContentService 的实例依赖了 AppDbContext (继承自 EF Core 的 DbContext)。在 TCPService 中通过 Thread.Start 启动了一个新的线程执行了 TCPService 中的 Receive 方法,在 Receive 方法中通过 ContentService 进行保存数据库的操作,而在访问 AppDbContext 的实例时出现对象已被 Disposed 的错误。
Object name: 'AppDbContext'. --->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 if 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.
针对这个问题,尝试改为通过构造函数注入 IServiceProvider ,在 TCPService.Receive (在新线程中执行的方法)中通过 IServiceScope 解析
using (var scope = _serviceProvider.CreateScope())
{
var contentService = scope.ServiceProvider.GetRequiredService<ContentService>();
//...
}
结果发现 IServiceProvider 也被 Disposed
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'IServiceProvider'.
由此可以推断在 ASP.NET Core 中在新建的线程中无法通过依赖注入的方式访问实现了 IDisposable 接口的对象(单例对象除外,但实现 IDisposable 接口的类型通常不会注册为单例),也就是只要请求一结束,实现 IDisposable 接口的对象的 Dispose 方法就会被调用。
那如何解决这个问题呢?
1)最下下策的解决方法是将 DbContext 注册为单例
services.AddDbContext<AppDbContext>(options => { }, ServiceLifetime.Singleton);
它会带来很多副作用,不考虑。
2)在保存数据至数据库的实现方法中基于 DbContextOptions (它是单例)手工 new AppDbContext ,用这个 DbContext 实例进行保存操作。
public class ContentService : Repository<Content>
{
private readonly DbContextOptions _options; public ContentService(AppDbContext Context, DbContextOptions options) : base(Context)
{
_options = options;
} public override async Task<bool> SaveAsync(Content entity)
{
using (var context = new AppDbContext(_options))
{
context.Set<Content>().Add(entity);
return await context.SaveChangesAsync() > ;
}
}
}
实测有效。
ASP.NET Core 新建线程中使用依赖注入的问题的更多相关文章
- ASP.NET Core - 在ActionFilter中使用依赖注入
上次ActionFilter引发的一个EF异常,本质上是对Core版本的ActionFilter的知识掌握不够牢固造成的,所以花了点时间仔细阅读了微软的官方文档.发现除了IActionFilter.I ...
- ASP.NET Core 1.0 中的依赖项管理
var appInsights=window.appInsights||function(config){ function r(config){t[config]=function(){var i= ...
- 在.NET Core控制台程序中使用依赖注入
之前都是在ASP.NET Core中使用依赖注入(Dependency Injection),昨天遇到一个场景需要在.NET Core控制台程序中使用依赖注入,由于对.NET Core中的依赖注入机制 ...
- dotnet core在Task中使用依赖注入的Service/EFContext
C#:在Task中使用依赖注入的Service/EFContext dotnet core时代,依赖注入基本已经成为标配了,这就不多说了. 前几天在做某个功能的时候遇到在Task中使用EF DbCon ...
- Asp.Net Core 第04局:依赖注入
总目录 前言 本文介绍Asp.Net Core中默认的依赖注入(DI)模式. 环境 1.Visual Studio 2017 2.Asp.Net Core 2.2 开局 第一手:依赖注入说明 1.一个 ...
- ASP.NET Core应用的7种依赖注入方式
ASP.NET Core框架中的很多核心对象都是通过依赖注入方式提供的,如用来对应用进行初始化的Startup对象.中间件对象,以及ASP.NET Core MVC应用中的Controller对象和V ...
- ASP.NET Core 配置文件(无处不在的依赖注入)
前烟: .NET Core 中取消了以往的 XML 节点配置文件,改用了 *.json 格式. 在 Startup.cs 文件中,构造方法 build appsetting.json 文件, 本文主要 ...
- asp.net core 系列之Dependency injection(依赖注入)
这篇文章主要讲解asp.net core 依赖注入的一些内容. ASP.NET Core支持依赖注入.这是一种在类和其依赖之间实现控制反转的一种技术(IOC). 一.依赖注入概述 1.原始的代码 依赖 ...
- ASP.NET Core MVC 控制器创建与依赖注入
本文翻译自<Controller activation and dependency injection in ASP.NET Core MVC>,由于水平有限,故无法保证翻译完全准确,欢 ...
随机推荐
- laravel 不理解的call方法
返回结果: 原来是调用同控制器的这四个方法之一...vendor\zhiyicx\plus-question\src\API2\Controllers\UserQuestionController.p ...
- C#概念总结(二)
1.C#的方法:<access Specifier> <Return Type>< Method Name>(Parmeter list){ method ...
- OrCAD Capture CIS 16.6 快速地编辑Part的引脚名称
操作系统:Windows 10 x64 工具1:OrCAD Capture CIS 16.6-S062 (v16-6-112FF) 工具2:Excel 参考1:http://www.360doc.co ...
- 数据库解析IP,时间戳
#解析IP SELECT INET_NTOA('168494269'); #解析时间戳 SELECT FROM_UNIXTIME('1505458308');
- python unittest装载、执行、造成报告
#执行用例 caselist = config.caselist for i in range(0,len(caselist)): reportname = caselist[i][2:] now = ...
- C++ Primer 笔记——类
1.定义在类内部的函数是隐式的inline函数. 2.因为this的目的总是指向“这个”对象,所以this是一个常量指针,我们不允许改变this中保存的地址. 3.常量成员函数:允许把const关键字 ...
- Django的Session存储Redis环境配置
第一步:在项目目录下的settings.py中MIDDLEWARE中加上中间件: # session中间件Django项目默认启用Session 'django.contrib.sessions.mi ...
- C# Enum 类型遍历
void Main() { new EnumForeach().Foreach(); } public class EnumForeach { public void Foreach() { fore ...
- Android 实现连续两次点击或连续多次点击退出应用
前言: 日常开发过程中,经常会遇到“连续点击两次退出应用”的需求(和“连续点击多次”的需求(如:手机从设置中进入开发者选项). 直接上代码:双击退出: private long exitTime = ...
- C# 之 HttpRequest 类
Request对象派生自HttpRequest类,使 ASP.NET 能够读取客户端在 Web 请求期间发送的 HTTP 值,从客户端获取信息,浏览器的种类,用户输入表单的数据,Cooki ...