我在ASP.NET核心2控制器中遇到了一个奇怪的问题。即使我没有随时打电话Dispose()
,我也有例外
_db.AesConnexions.Add(CurrentAesConnexion);
await _db.SaveChangesAsync(); //exception here
System.ObjectDisposedException :'无法访问已处置的对象。一个 此错误的常见原因是处理已解决的上下文 从依赖注入,然后尝试使用相同的 应用程序中其他位置的上下文如果你这可能会发生 正在上下文中调用Dispose(),或将上下文包装在一个 使用声明。如果你正在使用依赖注入,你应该让 依赖注入容器负责处理上下文 实例'。
此代码位于
中protected async Task SetupNewAesConnexionAsync()
{
_db.AesConnexions.Add(CurrentAesConnexion);
await _db.SaveChangesAsync(); //exception here if s/Task/void/
}
我在构造函数或
中调用public IActionResult Index()
楼上,我得到了以下构造函数(ctor)
public CookieController(IHttpContextAccessor httpContextAccessor,
MyDbContext dbContext)
{
_accessor = httpContextAccessor;
_db = dbContext;
}
(也许是一个重要的细节,CookieController
实际上被ContactController
用作子类:
public class ContactController : CookieController
{
public ContactController(IHttpContextAccessor httpContextAccessor, MyDbContext dbContext)
: base(httpContextAccessor, dbContext)
{
InitAes();
}
private async void InitAes()
{
await FindOrCreateAesConnexion(); // exception here when
// I have protected async Task SetupNewAesConnexionAsync()
}
}
(我检查CookieController
ctor在ContactController
ctor之前被调用过:
我在startup.cs中注册了类型:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MssqlLocalhost")));
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}
基本上我正在从Cookie ID信息中检索数据库中的数据,最终更新数据库(添加信息)。我想也许我在混淆混合同步和异步代码(从构造函数中调用异步代码),但我看不到任何问题或链接所描述的异常。
任何建议都将不胜感激。
答案 0 :(得分:0)
CurrentAesConnexion
来自哪里?它是控制器方法范围的本地吗?
我看到的一个明显问题是SetupNewAesConnexionAsync
方法返回void
而不是Task
。这样,实际的“等待”将起作用并将导致执行完成后继续:
protected async Task SetupNewAesConnexionAsync() {}
<强>更新强> 更新答案以包含完整分辨率。
原来问题是如何初始化与数据库的连接。它目前是在async
方法中完成的,从构造函数调用,但从未等待过。
修复是遵循async-init
模式(我发明了这个术语,没有官方的),描述here。这是更新的代码:
public class ContactController:CookieController { private readonly Task initTask;
public ContactController(IHttpContextAccessor httpContextAccessor, MyDbContext dbContext)
: base(httpContextAccessor, dbContext)
{
this.initTask = InitAes();
}
private async Task InitAes()
{
await FindOrCreateAesConnexion(); // exception here when
// I have protected async Task SetupNewAesConnexionAsync()
}
}
现在,无论在何处使用连接,都应首先等待initTask
,如下所示:
protected async Task SetupNewAesConnexionAsync()
{
await this.initTask;
_db.AesConnexions.Add(CurrentAesConnexion);
await _db.SaveChangesAsync();
}
答案 1 :(得分:0)
我相信您的问题是,当您调用异步InitAes()
方法时,不会使用await关键字调用它。因为没有等待该调用,所以在调用完成之前继续执行该方法。因此,已经处理了注入的依赖性。
public class ContactController : CookieController
{
public ContactController(IHttpContextAccessor httpContextAccessor, MyDbContext dbContext) : base(httpContextAccessor, dbContext)
{
await InitAes();
}
private async void InitAes()
{
await FindOrCreateAesConnexion();
}
}