注入IDbConnection与IDbConnectionFactory

问题描述 投票:4回答:2

TLDR:注入连接工厂与IDbConnection本身的原因是什么。

我目前正在.net MVC中使用Autofac将IDbConnection实例注入我的存储库类,以便与Dapper一起使用,如下所示:

Autofac设置:

builder.Register<IDbConnection>(ctx => new
    SqlConnection(conSettings.ConnectionString)).InstancePerRequest();

回购:

public ClientRepository(IDbConnection connection)
{
    _connection = connection;
}

public async Task<IEnumerable<Client>> GetAsync()
{
    string query = "SELECT * FROM Clients";
    return (await _connection.QueryAsync<Client>(query)).ToList();
}

到目前为止,这对我来说一直很好,但我有点担心连接保持开放而不被处理掉。

我在主题上找到的每个帖子都以某人建议传递连接工厂并在using语句中调用它为止,而没有真正提到为什么我当前的设置“糟糕”。

据我所知,每个请求应该得到它自己的IDbConnection,其中Dapper负责打开和关闭连接,Autofac负责处理。

这不是这种情况吗?我错过了什么吗?

c# asp.net-mvc autofac dapper
2个回答
3
投票

他们这样做我在ASP.NET核心项目上做这件事(跟我说一下,我知道它不是你正在使用的,但概念仍然适用)是通过存储库构造函数注入连接字符串。

正如您将看到的,我实际上注入了IConfiguration对象,因为由于其他要求,我需要配置文件中的其他设置。只是假装它是连接字符串。

然后我的存储库看起来像这样(粗略的例子,写在我的头顶,所以原谅我可能犯的任何错误):

public class FooRepository
{
    private readonly IConfiguration _configuration;

    public FooRepository(IConfiguration configuration)
    {
        _configuration = configuration
    }

    private IDbConnection Connection => new SqlConnection(_configuration.GetConnectionString("myConnectionString"));

    public Foo GetById(int id)
    {
        using (var connection = Connection)
        {
            return connection.QueryFirstOrDefault<Foo>("select * from ...", new {id});
        }
    }
}

汇总ADO.NET连接,根据需要打开一个连接,然后关闭它就像通常那样。使用using,即使异常被抛出,您也可以确保连接被关闭并处理 - 返回到池中 - 一旦完成。

当然,您可能希望将此公共代码提取到抽象超类,这样您就不需要在每个存储库中重复连接字符串的名称,也不需要重新实现Connection属性。

另外,正如我在评论中提到的,Dapper不负责打开或关闭连接,实际上它完全期望在你可以调用它的任何方法之前打开连接。 这不再是真的,对不起。


0
投票

如果您只注入IDbConnection,这意味着您的存储库只能使用该连接,并且您依靠IoC为您关闭/处置该连接。此外,如果您需要连接到两个不同的数据库,则不能,因为您只允许在此处创建一个连接。如果要并行运行查询,则不能,因为一次只能对一个数据库进行一次打开调用。最后,如果获取连接字符串有点困难并且不是直接来自配置文件(如KeyVault),那么您需要调用外部异步方法或IoC不允许您做的事情。

对我来说,我总是使用工厂,因为我想在完成后立即关闭任何连接,而不是等待IoC摆脱它。 (允许存储库外部的东西管理数据库连接感觉很脏。)我想控制我正在连接的数据库(我经常有超过1个DB,我必须使用)。我偶尔需要并行运行一堆不同的查询才能返回我需要的所有数据,因此我需要在一个方法中使用多个连接。我还必须做一些逻辑,因为我们将连接字符串存储在Azure Key Vault中,因此我必须执行异步调用以获取秘密信息,这有点复杂,因此工厂上的Create方法最终会执行工作繁重。

© www.soinside.com 2019 - 2024. All rights reserved.