C# EF 6-如何正确执行并行查询
创建报告时,我必须执行3个查询,这些查询涉及相同上下文中的独立实体。因为它们很重,我决定使用C# EF 6-如何正确执行并行查询,c#,.net,sql-server,entity-framework,C#,.net,Sql Server,Entity Framework,创建报告时,我必须执行3个查询,这些查询涉及相同上下文中的独立实体。因为它们很重,我决定使用.ToListAsync()
.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);
}
问题是:
EF不支持通过同一DbContext对象处理多个请求。如果在同一DbContext实例上的第二个异步请求在第一个请求完成之前启动(这就是关键所在),您将收到一条错误消息,表明您的请求正在针对开放的DataReader进行处理
资料来源:
您需要将代码修改为以下内容:
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(t1.Result, t2.Result);
}
异步任务GetE1Data()
{
使用(var MyCtx=new MyCtx())
{
返回等待MyCtx.E1.Where(blablabla.ToListAsync();
}
}
异步任务GetE2Data()
{
使用(var MyCtx=new MyCtx())
{
返回等待MyCtx.E2.Where(blablabla.ToListAsync();
}
}
异步任务DoSomething()
{
var t1=GetE1Data();
var t2=GetE2Data();
等待任务时(t1,t2);
剂量测定法(t1.结果,t2.结果);
}
退房
从文件中:
SELECT语句和BULK INSERT语句的语句交错
允许。然而,数据操作语言(DML)和数据定义
语言(DDL)语句以原子方式执行
然后,您的上述代码就可以工作了,并且您可以获得读取数据的性能优势。可能重复。一点提示。不要忘记在linq查询中调用AsNoQueryable。这将有助于提高性能您有什么例外?你能分享一些你如何并行执行查询的代码吗?@MiltonFilho“AsNoQueryable”?!?这听起来很可疑。。。谷歌对这种方法一无所知。。。这是一个框架吗?对不起,正确的是AsNoTracking。它会告诉EF不要观察所有对象的所有属性,并且会运行得很快。这样做是否有值得的性能提升?@Josh,这取决于它。如果多个调用(比方说10个调用)每个调用花费1秒,那么并行执行会导致总持续时间缩短,即按顺序运行时的10秒。但数据库引擎也有其局限性。如果你用并行请求轰炸它,它的资源消耗会增加。如果你想让加载的实体成为一个工作单元的一部分,并对它们进行更新,最后一起提交,那该怎么办?@mko你可能依赖于延迟加载,因此EF尝试加载其他数据,但由于上下文已被释放而失败。@binki:您可以将读取和写入分开:读取实体,将它们从上下文中分离。然后修改它们并将它们附加到单个上下文并保存更改。这并不能回答问题。