系统.InvalidOperationException:在配置上下文时尝试使用该上下文。

6

我实现了一个自定义的ASP.NET Core中间件,其中使用了数据库上下文作为依赖项。有时,对API的第一个请求抛出以下异常:

执行请求时发生未处理的异常。 System.InvalidOperationException:在配置时尝试使用上下文。由于此时仍在配置中,因此不能在OnConfiguring内部使用DbContext实例。如果在上一个操作完成之前在此上下文中启动了第二个操作,则不保证任何实例成员是线程安全的。

我只能在从SPA调用API时才能重现它。当我从Swagger调用API时,一切都正常工作。更改中间件的顺序并没有帮助。经过挖掘,我意识到middleware只会在应用程序中被实例化一次,而数据库上下文具有范围生存期。因此,问题可能在于直接将数据库上下文注入到middleware的构造函数中。我通过从构造函数中删除对数据库上下文的注入,并将其直接注入到InvokeAsync 方法中来修复了代码。这有所帮助,异常消失了。

虽然我解决了我的问题,但我还不太明白它是如何工作的。据我所知,EF.Core数据库上下文默认情况下注册为范围生存期,在ASP.NET Core应用程序中意味着每个新请求都会实例化一个新的上下文,并在完成后处理。因为我将数据库上下文注入到middleware的构造函数中,所以它应该在第一次请求完成后被处理,而且应该抛出这些异常或另一个异常,说明它正在尝试使用已经处理的上下文。此外,我完全不清楚为什么只有从SPA调用API时才会发生此错误,而对于所有Swagger请求都很好。


你可以使用类似Telerik的Fiddler来监控和比较SPA和Swagger请求,看看它们之间的区别。此外,你能否发布一些服务配置和中间件的代码示例? - Michael L.
2个回答

5
似乎我已经理解了。 我没有提到我在应用程序中使用的Autofac服务提供程序而不是默认服务提供程序,这实际上值得一提。 根据 ASP.NET Core文档 开发环境中的默认服务提供程序执行检查以验证:
- 作用域服务未直接或间接从根服务提供程序解析。 - 作用域服务未直接或间接注入单例。
显然,Autofac服务提供程序不执行此类检查,因此允许从根服务提供程序注入作用域服务。 根据文档
根服务提供程序的生命周期对应于提供程序随应用程序启动并在应用程序关闭时被处理的生命周期。
这就是为什么我的应用程序按预期工作,尽管我将作用域服务注入到单例中的原因。 它使用从根服务提供程序解析的DbContext实例,有时我在实际初始化上下文之前尝试执行对数据库的查询时可能会遇到这种情况。 这解释了这个问题的零星性质。

在使用Parallel.ForEach()container.Register...UsingFactoryMethod(() => new Context()).LifestyleTransient())时,我在Windsor中遇到了这个错误。 - Kellen Stuart
3
我在我的测试用例中遇到了完全相同的问题。你是如何解决它的? - Tanveer Badar

1

我曾经遇到过同样的问题,我按照这个问题中的答案解决了它。

我在数据库上下文中添加了“ServiceLifetime.Transient”选项。

在Startup.cs中添加了:

services.AddDbContext<TableContext>(opt =>
..otherOptions..,  ServiceLifetime.Transient);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接