EF 6 - 如何正确执行并行查询

时间:2017-01-19 19:15:38

标签: c# .net sql-server entity-framework

创建报告时,我必须执行3个涉及相同上下文的分离实体的查询。因为它们很重,所以我决定使用.ToListAsync();让它们并行运行,但是,令我惊讶的是,我得到了一个例外......

使用EF 6并行执行查询的正确方法是什么?我应该手动启动新任务吗?

编辑1
代码基本上是

using(var MyCtx = new MyCtx())
{
      var r1 = MyCtx.E1.Where(bla bla bla).ToListAsync();
      var r2 = MyCtx.E2.Where(ble ble ble).ToListAsync();
      var r3 = MyCtx.E3.Where(ble ble ble).ToListAsync();
      Task.WhenAll(r1,r2,r3);
      DoSomething(r1.Result, r2.Result, r3.Result);
}

2 个答案:

答案 0 :(得分:8)

问题在于:

  

EF不支持通过同一个DbContext对象处理多个请求。如果同一个DbContext实例上的第二个异步请求在第一个请求完成之前启动(这就是整点),那么您将收到一条错误消息,指出您的请求正在处理打开的DataReader。

来源:https://visualstudiomagazine.com/articles/2014/04/01/async-processing.aspx

您需要将代码修改为以下内容:

async Task<List<E1Entity>> GetE1Data()
{
    using(var MyCtx = new MyCtx())
    {
         return await MyCtx.E1.Where(bla bla bla).ToListAsync();
    }
}

async Task<List<E2Entity>> GetE2Data()
{
    using(var MyCtx = new MyCtx())
    {
         return await MyCtx.E2.Where(bla bla bla).ToListAsync();
    }
}

async Task DoSomething()
{
    var t1 = GetE1Data();
    var t2 = GetE2Data();
    await Task.WhenAll(t1,t2);
    DoSomething(r1.Result, r2.Result);
}

答案 1 :(得分:0)

签出https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/enabling-multiple-active-result-sets

从文档中:

  

SELECT和BULK INSERT语句的语句交织为   允许的。但是,数据操作语言(DML)和数据定义   语言(DDL)语句是原子执行的。

然后您的上述代码有效,您将获得读取数据的性能优势。