我们使用 Pomelo.EntityFrameworkCore.MySql(在底层使用 MySqlConnector)在实体框架中使用典型的 DbContext 方法建立 MySQL 连接。
services.AddDbContext<MyDbContext>(opt =>
opt.UseMySql(_mysqlConnectionString, _mysqlVersion, b =>
{
b.UseNewtonsoftJson();
})
);
然后我们在需要数据库连接的 some 控制器上使用依赖注入。例如:
public class ClientController : Controller
{
private readonly MyDbContext _context;
public ClientController(MyDbContext context)
{
_context = context;
}
}
这很好用。但是,我们有一些控制器不需要任何 MySQL 连接,因为它们不与数据库交互。一个例子是获取服务器时间。我们将它包装在它自己的控制器中,没有依赖注入:
[Produces("application/json")]
[Route("client")]
public class SimpleClientController : Controller
{
[HttpPost("GetTime")]
public IActionResult GetTime([FromBody] GetTimeRequest request)
{
var response = new GetTimeResponse()
{
Time = DateTime.UtcNow
};
return Json(response);
}
}
然而,似乎也为这些类型的请求创建了一个 MySQL 连接,这让我感到惊讶。我认为通过使用依赖注入,我们只会在控制器需要时创建 DbContext。在线阅读表明,实际上可以为 every 请求创建一个 DbContext,而不管所使用的控制器是什么。但是,我无法找到明确的答案,所以我希望堆栈溢出可以在这里提供帮助。例如,如果只创建一个 DbContext(不建立连接),文档并没有说清楚,等等。我很好奇 Pomelo 的 MySQL 框架的包含是否改变了这里的默认行为,也许他们创建了一个连接DbContext 创建?
我的问题:
是否真的会因为每个请求创建 DbContext 而创建 MySQL 连接(无论请求是否使用注入 DbContext 的控制器)?
有解决这个问题的简单方法吗?我只想为需要一个的请求创建一个 MySQL 连接。我目前正在探索在 DbContext 上使用 DbContextFactory 而不是 - 这似乎可以解决问题,但需要进行大量代码更改。
与此相关的任何其他评论都会有所帮助。
实际的数据库连接被合并,请参阅docs中的引用:
请注意,上下文池是正交于数据库连接池,后者在数据库驱动程序中的较低级别进行管理。
还有这个github问题:
除非您禁用了池(通过在连接字符串中设置 Pooling=false),打开和关闭连接的开销可以忽略不计,没有任何理由避免它。当一个连接关闭时,它会返回到池中,当一个连接打开时,它会从池中取出。这是默认/推荐的工作方式,而不是尝试实现您自己的连接重用。 Npgsql(和其他 ADO.NET 驱动程序)有一个高性能池(即将推出的 4.0 版本在这方面进一步提高了性能)。
所以你不应该太担心连接对象的创建
如 DBcontext pooling 文档所述(也与前一点相关):
DbContext 通常是一个轻型对象:创建和处置一个不涉及数据库操作,大多数应用程序都可以这样做,而不会对性能产生任何明显影响。
请注意,您可以包装工厂用法,因此最终用户代码不会更改(类似于 docs 中的示例):
serviceCollection.AddPooledDbContextFactory<YourContext>(...);
serviceCollection.AddScoped(sp =>
sp.GetRequiredService<IDbContextFactory<WhatsNewContext>>().CreateDbContext());