System.ObjectDisposedException没有在asp.net core 2控制器代码中的异步代码中调用Dispose()

时间:2018-02-22 22:53:40

标签: c# asp.net asp.net-mvc asp.net-core asp.net-core-mvc

我在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信息中检索数据库中的数据,最终更新数据库(添加信息)。我想也许我在混淆混合同步和异步代码(从构造函数中调用异步代码),但我看不到任何问题或链接所描述的异常。

任何建议都将不胜感激。

2 个答案:

答案 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(); 
    }
}