【问题标题】:How to handle postgresql db connections with dapper using dependency injection in .net core?如何使用 .net 核心中的依赖注入来处理与 dapper 的 postgresql db 连接?
【发布时间】:2019-11-19 08:26:02
【问题描述】:

我在我的 asp.net 核心 Web API 项目中使用 Dapper ORM 进行数据库操作。现在我每次都打开新的数据库连接并在 using 块中使用它,这样它们就会在作用域结束时被释放。但我希望在不使用 using 块的情况下处理所有这些连接,并且还希望自动处理它们。我正在寻找一种使用依赖注入来实现此目的的方法,因为它们会自动处理实现 IDisposable 的对象。

这是我处理所有数据库连接的方式:

在我的基础存储库中创建了一个 GetConnection 属性:

private IDbConnection _connection;

public IDbConnection GetConnection
{
    get
    {
        _connection = new NpgsqlConnection("Connection String");
        return _connection;
    }
}

使用块访问属性:

public async Task<IEnumerable<T>> GetAllAsync()
{
    IEnumerable<T> records = null;

    using (IDbConnection connection = GetConnection)
    {
        //db operations
    }

    return records;
}

那么我怎样才能使用依赖注入来实现相同的效果,它会在需要时初始化 IDbconnection 并在请求结束时处理,而无需将 IDbconnection 封装在 using 块内?

简而言之,我想避免每次都使用 GetConnection 属性来创建数据库对象,并避免使用 using 块来处理相同的对象。

【问题讨论】:

  • 为什么要删除using 块?建议最佳实践实际上是基于意见的,但您可以查看this。我猜您正在寻找 UoW-Per-Request 模式。链接中给出的解决方案可以帮助您实现这一目标。
  • 因为我想使用依赖注入来处理每个数据库连接,并且想避免在应用程序中使用块。
  • 就像这里描述的:stackoverflow.com/a/47403685/11748401 ..我只是想知道什么是最佳实践,处理这个链接中描述的数据库操作是否会很好?
  • 我不想在我正在执行数据库操作的应用程序中的任何地方都包含使用块。它们应该在请求结束时自动处理。
  • 简而言之,只是想问一下这里提供的答案:stackoverflow.com/a/47403685/11748401 是否推荐用于处理 Dapper 中的 DB 连接。另外,我明白你的意思是在 startup.cs 文件中注入 UoW 以避免使用块。但是,如果我们在 startup.cs 文件中注入 IDbconnection,它也会处理 DB 对象,因为 IDbconnection 也实现了 IDisposable,我们不需要在 UoW 中编写 dispose(),也不需要调用 dispose(),因为所有这些都将由IDb 自动连接。不管是什么操作,都会自动处理,

标签: asp.net-core dapper npgsql asp.net-core-3.0


【解决方案1】:

我是这样做的:

在startup.cs文件中添加Transient服务

services.AddTransient<IDbConnection>((sp) => new NpgsqlConnection("connectionString"));

在基本存储库构造函数中初始化 IDbconnection 对象,如:

class  RepositoryBase
{
    protected IDbConnection _connection;

    protected RepositoryBase(IDbConnection dbConnection)
    {
         _connection = dbConnection;
    }
}

并在我的存储库中执行数据库操作,例如

class XyzRepository : RepositoryBase
{
    public async Task<IEnumerable<T>> GetAllAsync()
    {
        IEnumerable<T> records = null;

        await _connection.ExecuteScalarAsync<object>("sqlQuery");

        return records;
    }

}

这将在请求结束时自动处理 IDbconnection 对象,而不使用 using 块。

来自答案的参考:How do I handle Database Connections with Dapper in .NET?

【讨论】:

  • 你读过cmets吗? ;)
  • 不需要使用 using 语句。 Dapper 会自动为你打开、关闭和释放连接。”这是不正确的。Dapper 会自动打开关闭的连接,它会自动关闭它自动打开的连接,但不会自动释放连接。Marc Gravell和 Eric Lippert 都主张在此处与 Dapper 一起使用。– MarredCheese 2021 年 7 月 9 日 20:07
【解决方案2】:

您不想只使用一个数据库连接来访问数据库。当一个数据库连接被释放时(在using 块的末尾),它会被返回给连接池,这比您自己想出的任何方案都更加高效和安全。

如果你想删除对NpgsqlConnection 的依赖,你应该创建一个连接工厂来创建IDbConnection 并将工厂插入到你的类中。 using 构造是好的和最佳实践,而不是您想要摆脱的东西。

还有更多关于连接池here

编辑:查看您的代码,我发现您已经将连接创建抽象化了。您的代码实际上很好。

【讨论】:

  • 我同意使用块处理对象并返回给连接池,这就是依赖注入在 .net 核心中所做的。如果我将 IDbConnection 作为 Transient 服务注入,它将自动处理数据库对象,而无需我为任何 DB 操作编写 using 块。
  • 就像这里描述的:stackoverflow.com/a/47403685/11748401 .. 我只是想知道什么是最佳实践,处理这个链接中描述的数据库操作是否好?
  • 我没有看到您链接到的答案中的连接被处理和回收。该连接将在存储库的整个生命周期内保持。
  • 连接将在请求结束时被释放,因为 IDbconnection 是使用诸如 services.AddTransient((sp) => new SqlConnection(dbConnectionString)) 之类的瞬态服务注入的;
  • 好的,感谢您强迫我阅读AddTransient。我仍然认为在整个请求中保持连接处于活动状态是一种不好的做法。应尽快处理连接。
猜你喜欢
  • 1970-01-01
  • 2018-12-14
  • 2021-08-23
  • 2019-02-16
  • 1970-01-01
  • 1970-01-01
  • 2020-01-17
  • 2021-03-02
  • 1970-01-01
相关资源
最近更新 更多