Obj*_*der 25 .net c# asynchronous entity-framework using
关于实体框架,有很长时间以来一直困扰着我.
去年我为使用EF的客户编写了一个大型应用程序.在开发过程中,一切都很顺利.
我们八月发货了.但几周后我开始在生产服务器上看到奇怪的内存泄漏.运行几天后,我的ASP.NET MVC 4进程占用了机器的所有资源(8 GB).这不好.我在网上搜索,看到你应该在一个using()
块中包围所有的EF查询和操作,以便可以处理上下文.
在一天中,我重构了我要使用的所有代码using()
,这解决了我的问题,因为这个过程依赖于稳定的内存使用.
我首先没有围绕我的查询的原因是我从Visualofite中包含的Microsofts自己的脚手架开始了我的第一个控制器和存储库,这些没有使用包围它的查询,而是它具有DbContext
作为实例变量的控制器本身.
首先:如果处理上下文非常重要(某些事情不会很奇怪,dbconnection
需要关闭等等),微软可能应该在他们的所有示例中都有这个!
现在,我已开始与我在我的后脑勺所有学习收获一个新的大项目工作,我一直在试用的.NET 4.5和EF 6的新功能async
和await
.EF 6.0具有所有这些异步方法(例如SaveChangesAsync
,ToListAsync
等等).
public Task<tblLanguage> Post(tblLanguage language)
{
using (var langRepo = new TblLanguageRepository(new Entities()))
{
return langRepo.Add(RequestOrganizationTypeEnum, language);
}
}
Run Code Online (Sandbox Code Playgroud)
在课堂上TblLanguageRepo
:
public async Task<tblLanguage> Add(OrganizationTypeEnum requestOrganizationTypeEnum, tblLanguage language)
{
...
await Context.SaveChangesAsync();
return langaugeDb;
}
Run Code Online (Sandbox Code Playgroud)
但是,当我现在在一个using()
块中包含我的语句时,我得到异常DbContext was disposed
,在查询能够返回之前.这是预期的行为.查询运行async,using
块在查询之前完成.但是在使用ef 6的async和await函数时,我应该如何以适当的方式处理我的上下文?
请指出我正确的方向.
是using()
需要EF 6?为什么微软自己的例子从未有过这样的特色?如何正确使用异步功能并处理上下文?
Ste*_*ary 24
你的代码:
public Task<tblLanguage> Post(tblLanguage language)
{
using (var langRepo = new TblLanguageRepository(new Entities()))
{
return langRepo.Add(RequestOrganizationTypeEnum, language);
}
}
Run Code Online (Sandbox Code Playgroud)
在返回之前处理存储库Task
.如果您制作代码async
:
public async Task<tblLanguage> Post(tblLanguage language)
{
using (var langRepo = new TblLanguageRepository(new Entities()))
{
return await langRepo.Add(RequestOrganizationTypeEnum, language);
}
}
Run Code Online (Sandbox Code Playgroud)
然后它将在Task
完成之前处置存储库.实际发生的是当你点击时await
,该方法返回一个不完整的Task
(注意该using
块在此时仍然是"活动的").然后,当langRepo.Add
任务完成时,该Post
方法继续执行并处理langRepo
.当Post
方法完成后,返回的Task
完成.
有关更多信息,请参阅我的async
介绍.
我会采用“每个请求一个DbContext”的方式,并在请求内重用DbContext。由于所有任务都应在请求结束时完成,因此您可以安全地再次处置它。
请参见ie:ASP.NET MVC中的每个请求一个DbContext(没有IOC容器)
其他优点:
using
语句会使您的代码混乱。我同意@Dirk Boer 的观点,即管理 DbContext 生命周期的最佳方法是使用 IoC 容器,该容器在 http 请求完成时处理上下文。但是,如果这不是一个选择,您也可以执行以下操作:
var dbContext = new MyDbContext();
var results = await dbContext.Set<MyEntity>.ToArrayAsync();
dbContext.Dispose();
Run Code Online (Sandbox Code Playgroud)
该using
语句只是用于在代码块末尾处理对象的语法糖。using
您只需调用自己即可达到相同的效果,无需阻塞.Dispose
。
想想看,如果您await
在 using 块中使用关键字,则不应出现对象处置异常:
public async Task<tblLanguage> Post(tblLanguage language)
{
using (var langRepo = new TblLanguageRepository(new Entities()))
{
var returnValue = langRepo.Add(RequestOrganizationTypeEnum, language);
await langRepo.SaveChangesAsync();
return returnValue;
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
16587 次 |
最近记录: |