实体框架6中的多异步?


87

这是我的代码:

var banner = context.Banners.ToListAsync()
var newsGroup = context.NewsGroups.ToListAsync()
await Task.WhenAll(banner, newsGroup);

但是当我从控制器调用函数时。显示错误

在先前的异步操作完成之前,第二操作在此上下文上开始。使用“ await”来确保在此上下文上调用另一个方法之前,所有异步操作都已完成。不保证任何实例成员都是线程安全的。

请帮我解决这个问题。


我有2个任务。如果我运行每个任务。成功了 但是如果我像上面的代码一样运行。它的错误
一个HV

Answers:


119

该异常清楚地说明了一次,每个上下文仅允许一个异步操作。

因此,await错误消息提示您要么一次只向他们一个:

var banner = await context.Banners.ToListAsync();
var newsGroup = await context.NewsGroups.ToListAsync();

或者,您可以使用多个上下文:

var banner = context1.Banners.ToListAsync();
var newsGroup = context2.NewsGroups.ToListAsync();
await Task.WhenAll(banner, newsGroup);

33
请注意,如果您有一个Lazy变量,即使在等待状态下也会在查询中使用上下文,则它会抛出相同的错误,只是在查询之前获取属性,要弄清楚这一点很麻烦。
Pedro.The.Kid 2014年

7
@ Pedro.The.Kid:通常,不要在异步数据库访问中使用延迟加载。延迟加载始终是同步的,因此对其他数据使用包含或单独的查询要好得多。
Stephen Cleary 2014年

1
是否有任何特定原因需要每个异步查询使用上下文?我觉得这成为一个很大的限制因素。
Zapnologica

1
@Zapnologica:这只是ES6的设计方式。每个上下文只能处理一个查询一次。因此,如果您在下一个查询开始之前完成一个查询,则只需要一个上下文。如果要同时执行多个查询,这只是一个问题。
Stephen Cleary

@StephenCleary,我很难找到该查询,因为在异常之前没有任何东西。有没有办法让我们找到当前正在执行的操作?谢谢
Fabio Milheiro '16


3

如果将Unity用于依赖项注入(例如,存储库模式),则使用带有create / update / delete的两个或多个上下文会得到以下错误:

无法定义两个对象之间的关系,因为它们已附加到不同的ObjectContext对象。

可以使用解决PerRequestLifetimeManager。更多信息在这里:

C#EF6使用Unity对一个上下文进行多个异步调用-Asp.Net Web Api

container.RegisterType<DbContext>(new PerRequestLifetimeManager());
container.RegisterType<ISupplierRepository, SupplierRepository>();
container.RegisterType<IContactRepository, ContactRepository>();
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.