如何使实体框架异步执行

Posted

技术标签:

【中文标题】如何使实体框架异步执行【英文标题】:How to make Entity Framework execute asynchronously 【发布时间】:2014-09-02 07:53:24 【问题描述】:

我在 ASP.Net MVC 5 应用程序中遇到异步控制器问题。 我正在使用 Entity Framework 6 Code First 方法。

我有办法

public async Task<ActionResult> Index()

    using(var context = new MyDbContext())
    
        var eventsTask = context.Events
            .Where(e => e.Enable)
            .ToListAsync();

        var countTask = context.Users
            .CountAsync();

        await Task.WhenAll(eventsTask, countTask);
        return View(new ViewModel()
        
            Events = eventsTask.Result, 
            Count = countTask.Result
        );
    

我这里有两个异步方法。我已经通过 MiniProfiler 分别测量了它们中的每一个。它们需要大约 85 毫秒。

但在我的方法中,我使用 Task.WhenAll() 运行它们。我相信它异步执行 Db 查询,两者都需要大约 85-90 毫秒。但它需要〜170-180。所以我让异步方法同步运行(彼此跟随)。

我认为这是因为上下文。我有一个测试,当我删除上下文查询并使用 HttpClient 调用许多 api 方法时。它需要的时间等于其中更长的时间(3 个 api 调用,每个约 500 毫秒。方法总共需要约 600 毫秒)。我相信可以异步执行 EF 方法。

有谁知道解决办法

【问题讨论】:

EF 是否支持并行操作?可能它只是将它们序列化。 尝试为每个任务使用不同的上下文并发布时间。 Mutil async entity framework 6?的可能重复 我已经阅读了这篇文章。我尝试了不同的上下文,但得到了相同的结果。 【参考方案1】:

这实际上不应该起作用,而是抛出异常。我猜第一个查询在第二个查询开始之前就完成了。

EF6 doesn't support multiple async operations on the same context.

await 每个查询(因此它们不会同时运行),或者为每个查询使用不同的上下文。

【讨论】:

它工作正常,没有任何 .但我也尝试使用不同的上下文得到相同的结果。 @GFoley83 不知道你为什么链接这个,但描述的答案不起作用【参考方案2】:

我发现了问题。

原因是 MiniProfiler.EF6。 1) 为了测量我的 sql 问题,我使用 MiniProfiler.EF6。即使我使用不同的 EF DBContext,这个框架也能避免并发 sql 查询。

2) 我禁用 MiniProfile.EF6 并运行我的应用程序。我对提到的 ken2k 有一个例外。为避免此异常,我遵循此答案 EF6 doesn't support multiple async operations on the same context.

3) 我测量 Dapper 和并发 SQL 查询。我在测试中使用了一个 SQLConnection 进行异步查询。我已经得到了结果:

a) 如果我对 Dapper 使用 SqlConnection,则执行查询 异步(并行)

b) 如果我使用来自 的 ProfiledDbConnection MiniProfiler 然后 Dapper 执行查询互相跟随(不是 并行)

【讨论】:

以上是关于如何使实体框架异步执行的主要内容,如果未能解决你的问题,请参考以下文章

如何使实体框架对每条记录使用 1 个更新查询而不是 1 个?

实体框架异步方法是不是使用 ThreadPool 线程?

实体框架 - 具有多个条件的异步选择

实体框架 - 使用 where 条件进行异步选择

实体框架 6 alpha 2 - 异步模式

实体框架异步操作需要十倍的时间才能完成