如何在 .NET Core 中使用依赖注入处理 PostgreSQL 数据库连接并使用 Dapper?

8
我正在我的asp.net core web API项目中使用Dapper ORM进行数据库操作。目前,每次都会打开新的数据库连接,并在using块内使用它,以便在作用域结束时将其处理掉。但是我想处理掉所有这些连接,而不使用 using 块,并且还想自动处理掉它们。我正在寻找一种使用依赖注入来实现此目的的方法,因为依赖注入会自动处理实现了IDisposable的对象。
以下是我如何处理所有DB连接的方式:
在我的基本存储库中创建了一个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 并在请求结束时销毁,而无需将 IDbconnection 封装在 using 块中?

简而言之,我想避免每次使用 GetConnection 属性来创建数据库对象,并消除使用 using 块来释放相同对象。


为什么您想要移除 'using' 块?建议最佳实践基本上是基于个人意见的,但您可以参考此链接。我猜您正在寻找 UoW-Per-Request 模式。链接中提供的解决方案可帮助您实现此目标。 - Amit Joshi
因为我想使用依赖注入来处理每个数据库连接,并且希望避免在应用程序中使用块。 - Sunny12
请按照此处所述进行翻译: stackoverflow.com/a/47403685/11748401 ..我只是想知道最佳实践是什么,是否最好像此链接中描述的那样处理数据库操作? 就如此处所述:stackoverflow.com/a/47403685/11748401.. 我只想知道最佳实践是什么,是否应该像链接中所描述的那样处理数据库操作? - Sunny12
我不想在我的应用程序中的每个进行数据库操作的地方都包含using块。它们应该在请求结束时自动释放。 - Sunny12
简单来说,我想问一下这里提供的答案:stackoverflow.com/a/47403685/11748401 是否建议在dapper中处理DB连接。另外,我明白您的意思是在startup.cs文件中注入UoW以避免使用块。但是,如果我们在startup.cs文件中注入IDbconnection,它也会释放DB对象,因为IDbconnection也实现了IDisposable,我们不需要在UoW中编写dispose(),也不需要调用dispose(),因为所有操作都将被IDbconnection自动处理。无论进行何种操作,它都将被自动处理。 - Sunny12
2个回答

8
我这样做:
在startup.cs文件中添加瞬态服务。
services.AddTransient<IDbConnection>((sp) => new NpgsqlConnection("connectionString"));

在基础存储库构造函数中初始化IDbconnection对象,例如:
class  RepositoryBase
{
    protected IDbConnection _connection;

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

我在我的Repositories中执行数据库操作,例如:

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

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

        return records;
    }

}

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

参考答案:如何在.NET中使用Dapper处理数据库连接?


你读了注释吗? ;) - felix Antony
不需要使用using语句。Dapper会自动为您打开、关闭和处理连接。"这是不正确的。Dapper将自动打开已关闭的连接,并自动关闭它自动打开的连接,但它不会自动处理连接。Marc Gravell和Eric Lippert都在这里倡导与Dapper一起使用using。- MarredCheese Jul 9 2021 at 20:07 - felix Antony
@felixAntony,你说得对,Dapper不会释放连接。然而,dotnet的依赖注入容器会在连接对象到达其生命周期(瞬态)的末尾时将其释放。这适用于任何实现“IDisposable”的容器创建的对象。 - Steve Lillis

2
您不应仅使用一个数据库连接进行数据库访问。当数据库连接被处理(在using块的结尾处)后,它将返回到连接池,这比您自己想出的任何方案都更有效和安全。
如果您想要消除对NpgsqlConnection的依赖性,您应该创建一个连接工厂来创建IDbConnection并将其插入到您的类中。 using结构是良好的最佳实践,而不是您想要摆脱的东西。
有关连接池的更多信息,请单击此处编辑:查看您的代码,我看到您已经将连接创建抽象化了。您的代码实际上很好。

我同意使用块来处理对象并将其返回到连接池,这也是.NET Core中依赖注入的作用。如果我将IDbConnection注入为瞬态服务,它将自动处理数据库对象的处理,而无需为任何DB操作编写using块。 - Sunny12
请按照此处所述的方式进行翻译:https://dev59.com/9mox5IYBdhLWcg3wbDok#47403685 .. 我只想知道最佳实践是什么,是否最好像链接中描述的那样处理数据库操作? - Sunny12
我在您提供链接的答案中并未看到连接被处理和回收。连接将保留存储库的生命周期。 - Palle Due
1
连接将在请求结束时被释放,因为IDbconnection是使用瞬态服务注入的,例如services.AddTransient<IDbConnection>((sp) => new SqlConnection(dbConnectionString));。 - Sunny12
我想这也可能会有所帮助,因为所有的数据库操作都将仅使用该对象执行。只是分享我的想法,不确定它是否在所有情况下都有益。 - Sunny12
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接