.Net Core 程序报错 在上一个操作完成之前,在此上下文上启动了第二个操作。
错误一:
程序完整报错:
A second operation started on this context before a previous operation completed. This is usually caused by different threads using the same instance of DbContext, however instance members are not guaranteed to be thread safe. This could also be caused by a nested query being evaluated on the client, if this is the case rewrite the query avoiding nested invocations.
中文翻译:
在上一个操作完成之前,在此上下文上启动了第二个操作。这通常是由使用同一DbContext实例的不同线程造成的,但是实例成员不能保证线程安全。这也可能是由于在客户机上计算的嵌套查询造成的,如果是这种情况,请重写查询以避免嵌套调用。
出现这个问题的原因是,我的数据库注入用的是单例模式,然后我在一个异步方法里用Task.Factory.StartNew开启了一个新线程,然后在这个新线程里操作了数据库。之后就发现这个错了。
解决办法:
1、避免在新开启的线程里操作数据库,可以单独封装方法然后通过返回值的方式去做一些处理。
2、重新New一个上下文
var optionsBuilder = new DbContextOptionsBuilder<SqlContext>(); optionsBuilder.UseSqlite(Configuration.GetConnectionString("Sqlite")); using (var context = new SqlContext(optionsBuilder.Options)) { //操作数据库的时候用context去保存 }
错误二:
完整错误:
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.
Object name: 'SqlContext'.
中文翻译:
无法访问已释放的对象。此错误的一个常见原因是释放从依赖项注入解析的上下文,然后稍后尝试在应用程序的其他位置使用相同的上下文实例。如果对上下文调用Dispose()或在using语句中包装上下文,则可能会发生这种情况。如果使用依赖项注入,则应让依赖项注入容器负责处理上下文实例。
对象名:“SqlContext”。
出现这个问题的原因是,发现第一个错误之后,我想那我不注入单例注入成别的类型不就好了,然后下面的错误就诞生了。其实还是和我在一个异步方法里用Task.Factory.StartNew开启了一个新线程,然后在这个新线程里操作了数据库有关。
解决办法:
既然说上下文释放了那我再New一个好了,和上面的解决办法一样。
var optionsBuilder = new DbContextOptionsBuilder<SqlContext>();
optionsBuilder.UseSqlite(Configuration.GetConnectionString("Sqlite"));
using (var context = new SqlContext(optionsBuilder.Options))
{
//操作数据库的时候用context去保存
}
这两种错误的发生,其实最终的解决方案就是不要在新开的线程里操作数据库,尽量避免就行了,就不用特殊处理了。
——————————————————————————————————————————————————————————
最近新做的项目,这个问题又出现了,这里补充一下
错误三:当数据量大的时候,连接持续时间太长也会被回收
我操作数据量特别大的时候,保存的时候报错,连接被释放了,没办法重新创建上下文一个好了,办法同上。
var optionsBuilder = new DbContextOptionsBuilder<SqlContext>(); optionsBuilder.UseSqlite(Configuration.GetConnectionString("Sqlite")); using (var context = new SqlContext(optionsBuilder.Options)) { //操作数据库的时候用context去保存 }