排队EF查询

时间:2016-06-17 10:28:14

标签: c# entity-framework entity-framework-6 async-await

在Windows桌面应用程序中,只要视图存在,上下文就会存在,那么避免“在上一次异步操作完成之前在此上下文中启动第二个操作”错误的最佳方法是什么?

在我的视图模型中,我收到了一个存储库实例(通过构造函数),它包装了一个长期存在的DbContext实例,当我需要加载一些数据时,例如,如果我从同一个方法执行它,那么我可以在异步方法中等待它们,这可以确保它们同步执行。

但是,想象一下我有这个:

private async void SomeMethodA()
{
    await Context.GetA();
}

private async void SomeMethodB()
{
    await Context.GetB();
}

它们被声明为void,因为它们实际上是一些事件处理程序。所以,我的代码执行SomeMethodA(),这个数据库调用可能需要2秒。因此,代码执行返回到UI线程,然后某些东西(用户或代码)触发SomeMethodB(),这将引发上述异常。

确保异步数据库调用排队的最佳方法是什么?存储库是处理此问题的最佳位置吗?

2 个答案:

答案 0 :(得分:2)

  

什么是最好的避免方式?在先前的异步操作完成之前,在此上下文中启动了第二个操作'错误?

始终await您的异步调用。

  

我可以在异步方法中等待它们中的每一个,这可以确保它们同步执行。

它们将异步执行,而不是同步执行。但是,他们将连续执行(一次一个),我认为这就是你的意思。

  

它们被声明为void,因为它们实际上是一些事件处理程序。

这就是你的问题。他们必须等待。他们不能成为事件处理程序,抱歉。您必须修改应用程序设计的这一部分。即使您解决了这个问题(例如,通过每个请求打开多个数据库连接),由于async void使用"异步模块或处理程序在异步时完成,您仍会遇到问题手术还在等待#34;异常。

  

代码执行返回UI线程

这里没有UI线程。执行只返回给调用者。

答案 1 :(得分:1)

您可能最好将您的上下文设置为使用它的方法的本地化,如https://msdn.microsoft.com/en-us/data/jj729737.aspx和几个SO答案中所述。我不太了解等待,但我的第一个猜测是:

private async void SomeMethodA()
{
    using (var myContext = new Context()) // or, possibly, new Entities()
    {
        await myContext.GetA();
    }
}