为什么使用DbContext池?
DbContext是Entity Framework中最重要的类型之一,它提供了一种连接数据库并执行查询和更新的方式。在一个ASP.NET Core应用程序中,每次请求都可能需要对数据库进行一次或多次查询。在这种情况下,为每个请求创建新的DbContext实例并不是一个好的选择,因为这样做可能会导致内存和性能问题。
DbContext池允许应用程序在需要时重用已经创建的DbContext实例,从而提高性能并减少内存消耗。
性能基准
DbContext池的工作原理
DbContext池是一个对象池,它维护一组可用的DbContext实例,这些实例是预先创建好的,缓存在池子中。当应用程序需要一个新的DbContext实例时,它可以从池子中获取一个已有的实例,使用完后再将其释放回池子中,以供下一次使用。
DbContext池的大小是由应用程序的配置来控制的。默认情况下,DbContext池的大小是1024,但是我们也可以通过代码进行手动配置。例如,我们可以使用以下代码手动配置DbContext池的大小:
Services.AddDbContextPool<DbContext>(options => options.UseSqlServer(""), poolSize: 10);
在这里,我们将DbContext池的大小设置为10个实例。
超过poolSize会怎么样?
微软官网:一旦超过 poolSize,就不会缓存新的上下文实例,EF 会回退到按需创建实例的非池行为。
DbContext池中每个DbContext的生命周期
每个DbContext实例代表了应用程序与数据库的会话(Session),池中每个DbContext实例的生命周期与依赖注入时的声明周期有关,默认DbContext是以范围生命周期(Scope)注册服务的(这是最佳的方式)。
微软官网:Entity Framework Core 不支持在同一 DbContext 实例上运行多个并行操作。 这包括异步查询的并行执行以及从多个线程进行的任何显式并发使用。 因此,始终立即 await 异步调用,或对并行执行的操作使用单独的 DbContext 实例。
释放DbContext池中的DbContext
官方推荐使用自定义上下文工厂:看文档(管理共用上下文中的状态)这里与文档冲突,我就不说了。
总结
DbContext池是为了提高性能而引入的概念。它可以缓存DbContext实例,避免了创建和销毁DbContext实例的开销,同时还可以减轻数据库的负担。