介绍:上下文的声明周期开始于实例化,结束于垃圾回收器回收并释放
现有流行方法使用using来操作上下文(try/finally)
在使用上下文的过程中谨记一个原则:一个请求对应一个上下文
下面简单介绍三种使用上下文的方式
1、Using Patten
优点:自动释放上下文
缺点:不能在应用程序中共享上下文,代码复用性不高
Using(var conn=new DbContent)
{
...
}
2、DisPose Pattern
优点:当请求执行完成之后会自动释放上下文,
缺点:很难保证共享上下文,需要所有开发者使用DisPose模式
public class EntityController:Controller{
private EbDbContent _content;
public BlogController()
{
_content=new EbDbContent();
}
Protected override void Dispose(bool disposing)
{
if(disposing)
{
_context.Dispose();
}
Vase.DisPose(disposing);
}
}
3、Dependency Injection
优点:通过依赖注入能够减轻控制器实例化上下文的负担,不需要担心上下文生命周期何时结束
public class EntityController:ontroller
{
private EFDbContext _context;
public BlogController(EFDbContext context)
{
_context=context
}
}
生命周期追溯
上下文实例实现了工作单元模式,
工作单元模式:用于维护受业务事务的影响,并协调写入数据库的变更和解决并发问题。
管理上下文实例的生命周期独立于业务事务的声明周期,将上下文的声明周期和业务事务的声明周期隔离开来
1、性能考虑:每个上下文实例都维护着从数据库中所有实体加载中的一级缓存,无论何时需要巡查数据,默认情况需要从数据库中获取数据,但是此时将试图从一级缓存中获取数据。由于一级缓存的存在,在跨多个业务事务中使用相同上下文实例将减少和数据库交互的次数
2.延迟加载。如果服务返回的是poco实体而非经过DTO转换过够的实体,我们希望在这些实体上使用延迟加载,检索出的所有实体的上下文实例的生命周期将超出业务事务的生命周期的范围。
上下文的声明周期可以独立于业务事务的声明周期
保持上下文的生命周期很短暂,如果过长,在多个业务事务中会使得一级缓存不会是最新的,从而导致并发问题。
不能够在多线程中访问上下文,会造成多次查询通过相同的数据库连接同事并发返回,也会破坏通过上下文维护实体的变更追踪和工作单元的一级缓存。
如果在多线程中使用数据库链接,必须保证每个上下文的链接都是独立的。
EF6中支持在多线程中查询一次,如果查询多次将抛出NotSupportedException的异常
可以通过
1.DbSet<T>.ToListAsync()
2.FirstOrDefaultAsync()启动多个查询
async Task MultpleAsyncQuery()
{
Using(var conn=new DbContent)
{
List<Task> task=new List<task>
{
var alltask=MultpleAsyncQuery();
await allTasks;
}
}
}
解决上述问题的办法:
1:在多个异步查询中使用awit关键字
2:对每个异步查询操作使用不同的上下文派生类实例,在EF6中,异步查询功能支持异步编程模型,但是不支持并行
资料来自书籍《你必须掌握的EntityFramework 6.x与.ne core 2.0》
本人第一次博客,如果有问题,请大佬们及时指出,