在 EntityFramework 中避免每个请求的 MySQL 连接

问题描述 投票:0回答:1

我们使用 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 创建?

我的问题:

  1. 是否真的会因为每个请求创建 DbContext 而创建 MySQL 连接(无论请求是否使用注入 DbContext 的控制器)?

  2. 有解决这个问题的简单方法吗?我只想为需要一个的请求创建一个 MySQL 连接。我目前正在探索在 DbContext 上使用 DbContextFactory 而不是 - 这似乎可以解决问题,但需要进行大量代码更改。

  3. 与此相关的任何其他评论都会有所帮助。

c# mysql entity-framework pomelo-entityframeworkcore-mysql
1个回答
0
投票
  1. 例如,如果只创建一个DbContext(不建立连接),文档并没有说清楚

实际的数据库连接被合并,请参阅docs中的引用:

请注意,上下文池是正交于数据库连接池,后者在数据库驱动程序中的较低级别进行管理

还有这个github问题

除非您禁用了池(通过在连接字符串中设置 Pooling=false),打开和关闭连接的开销可以忽略不计,没有任何理由避免它。当一个连接关闭时,它会返回到池中,当一个连接打开时,它会从池中取出。这是默认/推荐的工作方式,而不是尝试实现您自己的连接重用。 Npgsql(和其他 ADO.NET 驱动程序)有一个高性能池(即将推出的 4.0 版本在这方面进一步提高了性能)。

所以你不应该太担心连接对象的创建

  1. 我目前正在探索使用 DbContextFactory 而不是 DbContext

DBcontext pooling 文档所述(也与前一点相关):

DbContext 通常是一个轻型对象:创建和处置一个不涉及数据库操作,大多数应用程序都可以这样做,而不会对性能产生任何明显影响。

请注意,您可以包装工厂用法,因此最终用户代码不会更改(类似于 docs 中的示例):

serviceCollection.AddPooledDbContextFactory<YourContext>(...);
serviceCollection.AddScoped(sp => 
    sp.GetRequiredService<IDbContextFactory<WhatsNewContext>>().CreateDbContext());
© www.soinside.com 2019 - 2024. All rights reserved.