Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 避免在同一DbContext上同时运行多个任务时出现实体框架错误_C#_Sqlite_.net Core_Entity Framework Core_Dbcontext - Fatal编程技术网

C# 避免在同一DbContext上同时运行多个任务时出现实体框架错误

C# 避免在同一DbContext上同时运行多个任务时出现实体框架错误,c#,sqlite,.net-core,entity-framework-core,dbcontext,C#,Sqlite,.net Core,Entity Framework Core,Dbcontext,我在一个Dotnet核心项目中有一个WebApi控制器,该项目使用Sqlite运行Entity Framework核心 操作中的此代码偶尔会产生错误: var t1 = _dbContext.Awesome.FirstOrDefaultAsync(a => [...]); var t2 = _dbContext.Bazinga.FirstOrDefaultAsync(b => [...]); var r1 = await t1; var r2 = await t2; 错误如下:

我在一个Dotnet核心项目中有一个WebApi控制器,该项目使用Sqlite运行Entity Framework核心

操作中的此代码偶尔会产生错误:

var t1 = _dbContext.Awesome.FirstOrDefaultAsync(a => [...]);
var t2 = _dbContext.Bazinga.FirstOrDefaultAsync(b => [...]);
var r1 = await t1;
var r2 = await t2;
错误如下:

  • Microsoft.EntityFrameworkCore.Query.RelationalQueryCompilationContextFactory:错误: 在数据库中迭代某个事件的结果时发生异常 查询System.ObjectDisposedException:安全句柄已关闭

  • Microsoft.EntityFrameworkCore.Query.RelationalQueryCompilationContextFactory:错误: 在数据库中迭代某个事件的结果时发生异常 查询System.InvalidOperationException:ExecuteReader只能是 连接打开时调用

对我来说,这两个错误都表明
DbContext
中存在一些问题,比如过早处理(尽管不是
DbContext
本身)。
DbContext
正在使用Dotnet核心的管道“常规方式”将配置注入控制器构造函数,如下所示(从我的
Startup.cs
ConfigureServices
方法体):

。。。我没有看到上面提到的错误,因此得出的结论是,在我的
DbContext
(如上所述注入)的同一个实例上并发运行多个任务是导致问题的原因。显然,这是一个意外的结果

问题:

  • 我是得出了正确的结论,还是有其他的事情发生
  • 你能指出错误只是偶尔发生的原因吗
  • 您知道在
    DbContext
    上运行并发任务时有什么简单的方法可以避免这个问题吗

  • 不幸的是,你不能这样做

    EF Core不支持在同一上下文实例上运行多个并行操作。在开始下一个操作之前,应始终等待操作完成。这通常是通过在每个异步操作上使用await关键字来完成的

    也从

    线程安全 虽然线程安全会使异步更有用,但它是一个正交特性。鉴于EF与由用户代码组成的图形交互以维护状态,并且没有简单的方法来确保此代码也是线程安全的,因此我们不清楚在最一般的情况下是否能够实现对它的支持

    目前,EF将检测开发人员是否试图同时执行两个异步操作并抛出


    DbContext
    在任何时间点仅支持单个打开的数据读取器。如果要同时执行多个数据库查询,则需要多个
    DbContext
    实例,每个并发查询一个实例

    至于为什么偶尔会发生错误,这是一个竞争条件。仅仅因为您一个接一个地开始两个任务(不等待),并不保证数据库会同时被命中。有时,执行时间正好排成一行,而有时一个任务可能会在另一个任务启动时正确完成,因此没有冲突

    如何避免它-不要因为它不受支持而这样做。等待每个DbContext调用或使用多个DbContext实例


    我所说的查询是指任何数据库操作,包括选择、更新、删除、插入、更改、存储过程调用等

    我理解,当然,我意识到,我可以通过不这样做来避免它;)我知道你以前也遇到过类似的问题。我以前没找到,因为我找不到要找的东西。特别感谢您提供的文档参考-这是一个陷阱。我很好奇为什么我没有收到前面提到的显式“不执行并发异步”错误。@OskarLindberg-EF6内置了一个检查,试图检测它是否以这种方式使用,并将失败并显示正确的错误消息。我猜他们没有将相同的检查构建到EF Core中,因此一旦发生冲突,检查就会失败,但如果两个(或更多任务)恰好安全地相互传递,那么(幸运的是?)执行调用就会成功。@Igor您可能还想链接到声明不支持并行查询的。
    services.AddDbContext<ApplicationContext>(options => options.UseSqlite(connectionString));
    
    var r1 = await _dbContext.Awesome.FirstOrDefaultAsync(a => [...]);
    var r2 = await _dbContext.Bazinga.FirstOrDefaultAsync(b => [...]);