实体框架6,加载实体async / await

时间:2016-05-12 06:50:12

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

我想从db重新加载某些实体,因为我希望使用async / await重新加载它们。这是我的代码:

private async void btnUpdate_Click(object sender, EventArgs e)
{
 Task allTasks = UpdateAppointments();
 await allTasks;
}
 internal async Task UpdateAppointments()
 {

        IEnumerable<Entities.Apointment> apps = PContext.Appointments.Select(p => p).Where(p => p.Start >= Start && p.End <= End && p.MachineId == 66);

        List<Task> task = new List<Task>();

        foreach (Entities.Apointment app in apps)
        {

            task.Add(PContext.Entry(app).ReloadAsync());

        }
        await Task.WhenAll(task);
    }

我收到错误:

  

在上一次异步操作完成之前,在此上下文中启动了第二个操作。使用&#39;等待&#39;确保任何   在调用另一个方法之前已完成异步操作   在这种背景下。任何实例成员都不能保证是线程   安全的。**

异常详情:

  

{System.NotSupportedException:在上一个异步操作完成之前,在此上下文中启动了第二个操作。使用&#39;等待&#39;确保在调用此上下文中的另一个方法之前已完成任何异步操作。任何实例成员都不保证是线程安全的。      在System.Data.Entity.Internal.ThrowingMonitor.EnsureNotEntered()      at System.Data.Entity.Core.Objects.ObjectContext.RefreshAsync(RefreshMode refreshMode,Object entity,CancellationToken cancellationToken)      在System.Data.Entity.Internal.InternalEntityEntry.ReloadAsync(CancellationToken cancellationToken)      在System.Data.Entity.Infrastructure.DbEntityEntry`1.ReloadAsync()      在C:\ Git \ planningmodule \ PlanningModule \ PlanningForm.cs中的PlanningModule.PlanningForm.d__20.MoveNext():第307行   ---从抛出异常的先前位置开始的堆栈跟踪结束---      在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)      在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)      在System.Runtime.CompilerServices.TaskAwaiter.GetResult()      在C:\ Git \ planningmodule \ PlanningModule \ PlanningForm.cs中的PlanningModule.PlanningForm.d__19.MoveNext():第264行}

内部异常:

  

堆栈追踪:

  

_stackTrace {sbyte [192]} object {sbyte []}

Anys的想法,如何重新加载实体异步?

1 个答案:

答案 0 :(得分:2)

您需要具体化列表,然后才能对DbContext执行其他操作,因为在您枚举DbContext时正在使用IQueryable。因此,添加.ToList()可以解决问题,因为在迭代开始之前,所有实体都会从DbContext中检索出来。

foreach (Entities.Apointment app in apps.ToList()) // added ToList()

如果您想使用async来实现列表,则可以

foreach (Entities.Apointment app in (await apps.ToListAsync()))

编辑 来自评论

  

我应该注意到,我得到的错误通常与重新加载的许多实体有关(&gt; 1000)

我能想到的唯一另一件事是await Task.WhenAll(task);中存在竞争条件,其中任务(您在此声明之前的循环中定义)同时调用{ {1}}。没有其他信息,我无法确切地告诉你(让我知道它是完全相同的错误还是不同的错误)。在这种情况下,您应该在循环内同步执行每个调用,这仍然可以使用await / async调用来完成。

DbContext
相关问题