C# 在MVC控制器中,需要异步返回EntityFramework CodeFirst数据
我想在我的ASP.NET MVC控制器中使用异步/等待模式。我发现了错误 ObjectContext实例已被释放,无法再使用 最终,我想缓存我的结果,但现在我认为第一步是要弄清楚如何使用EF并使用async/await返回C# 在MVC控制器中,需要异步返回EntityFramework CodeFirst数据,c#,asp.net-mvc,ef-code-first,async-await,C#,Asp.net Mvc,Ef Code First,Async Await,我想在我的ASP.NET MVC控制器中使用异步/等待模式。我发现了错误 ObjectContext实例已被释放,无法再使用 最终,我想缓存我的结果,但现在我认为第一步是要弄清楚如何使用EF并使用async/await返回 public class SpeakerController : Controller { public async Task<ActionResult> Index() { using (v
public class SpeakerController : Controller
{
public async Task<ActionResult> Index()
{
using (var context = new MultiTenantContext())
{
var speakersAll = await context.Speakers.ToListAsync();
return View("Index", speakersAll);
}
}
公共类扬声器控制器:控制器
{
公共异步任务索引()
{
使用(var context=new multi-tenantcontext())
{
var speakersAll=wait context.Speakers.ToListAsync();
返回视图(“索引”,speakersAll);
}
}
找到的解决方案:
private MultiTenantContext context = new MultiTenantContext();
public async Task<ActionResult> Index()
{
var speakersAll = await context.Speakers.ToListAsync();
return View("Index", speakersAll);
}
private MultiTenantContext context=new MultiTenantContext();
公共异步任务索引()
{
var speakersAll=wait context.Speakers.ToListAsync();
返回视图(“索引”,speakersAll);
}
正如我在下面的评论中所说,当ToListAsync()实际执行时,将上下文从using中拉出会导致它不会被释放。如果您懒散地加载Speaker.Sessions,您的上下文在使用时早已消失,因此会出现问题 请尝试以下方法:
await context.Speakers.Include(x => x.Sessions).ToListAsync();
确保在上下文超出范围之前加载会话
您可以使用不同的模式;例如,允许上下文存活更长的时间,但我个人认为,如果您不需要某种工作单元模式,那么像您所做的那样,在use()
块中使用非常短的上下文是最好的
虽然这不是这里的问题-您也不应该在EF中将延迟加载与异步等待混合使用:如果您是延迟加载Speaker.Sessions,那么您的上下文在使用时早已消失,因此存在问题 请尝试以下方法:
await context.Speakers.Include(x => x.Sessions).ToListAsync();
确保在上下文超出范围之前加载会话
您可以使用不同的模式;例如,允许上下文存活更长的时间,但我个人认为,如果您不需要某种工作单元模式,那么像您所做的那样,在use()
块中使用非常短的上下文是最好的
虽然这不是这里的问题-您也不应该在EF中将延迟加载与异步等待混合使用:您应该避免在web应用程序中使用延迟加载,因为目标是最小化HTTP请求的响应时间,而这最好是通过更少的数据库请求来实现的。特别是在MVC和/或web API中,您的通过特定的操作方法,在大多数情况下,应该可以准确地确定您的数据需求,并将其包含在一个或很少的请求/查询中。这会减少数据库服务器的负载,并提高web请求的性能 至于使用语句和dbcontext,如果可以的话,您不应该在控制器中实例化dbcontext。最好是注入它们,并让容器确定如何管理它们的生存期。通常,您希望每个请求只有一个dbcontext实例,这对所有请求都可用(尽管这些可能很少)在请求生命周期内需要EF进行的查询。如果您使用StructureMap(我的首选),您可以通过以下方式实现:
For<DbContext>.HybridHttpOrThreadLocalScoped().Use<MyContext>();
.HybridHttpOrthReadLocalScope().Use()的;
(请注意,此语法已使用StructureMap 4更新)
如果您不确定您是否信任我的建议,请考虑EF7进一步采纳该建议,使得不使用依赖注入来很难与EF7和MVC 6一起工作,以促使开发人员朝着正确的方向发展(落入“成功的坑”)。。有关示例(),请参见官方asp.net文档中的EF7/MVC6教程
摘录: 请注意,我们没有为Logger和BookContext设置任何值 依赖注入(DI)子系统自动设置这些 DI还处理对象的生存期,因此 不需要调用Dispose。有关详细信息,请参阅依赖项 注射您应该避免在web应用程序中使用延迟加载,因为目标是最小化HTTP请求的响应时间,而这最好是通过更少的数据库请求来实现的。特别是对于MVC和/或web API,您有非常精细的操作方法,在大多数情况下,应该可以准确地确定您的数据需要什么rements在一个或很少的请求/查询中包含这些内容。这会减少数据库服务器的负载,并为web请求带来更好的性能 至于使用语句和dbcontext,如果可以的话,您不应该在控制器中实例化dbcontext。最好是注入它们,并让容器确定如何管理它们的生存期。通常,您希望每个请求只有一个dbcontext实例,这对所有请求都可用(尽管这些可能很少)在请求生命周期内需要EF进行的查询。如果您使用StructureMap(我的首选),您可以通过以下方式实现:
For<DbContext>.HybridHttpOrThreadLocalScoped().Use<MyContext>();
.HybridHttpOrthReadLocalScope().Use()的;
(请注意,此语法已使用StructureMap 4更新)
如果您不确定您是否信任我的建议,请考虑EF7进一步采纳该建议,使得不使用依赖注入来很难与EF7和MVC 6一起工作,以促使开发人员朝着正确的方向发展(落入“成功的坑”)。。有关示例(),请参见官方asp.net文档中的EF7/MVC6教程
摘录: 请注意,我们没有为Logger和BookContext设置任何值 依赖注入(DI)子系统自动设置这些 DI还处理对象的生存期,因此 不需要调用Dispose。有关详细信息,请参阅依赖项 注射哪一行是抛出错误的?