You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Autofac为Dapper创建IDbConnection工厂解决并行操作问题

问题根因

你之前使用InstancePerLifetimeScope注册IDbConnection的方式,会导致同一个生命周期作用域内仅存在一个SqlConnection实例,而SqlConnection本身是非线程安全的,多线程并行操作时争抢同一个连接实例就会出现并发冲突、操作异常等问题。

实现方案

你可以通过以下两种方式实现连接工厂,解决并行操作的问题:


方案一:自定义连接工厂(更易扩展、易测试)

1. 定义工厂接口与实现

// 工厂接口
public interface IDbConnectionFactory
{
    IDbConnection Create();
}

// SqlServer连接工厂实现
public class SqlConnectionFactory : IDbConnectionFactory
{
    private readonly string _connectionString;

    public SqlConnectionFactory(string connectionString)
    {
        _connectionString = connectionString;
    }

    public IDbConnection Create()
    {
        // 每次调用都返回新的连接实例
        return new SqlConnection(_connectionString);
    }
}

2. Autofac 注册配置

// 工厂本身无状态,可注册为单例
builder.RegisterInstance(new SqlConnectionFactory(_connectionString))
       .As<IDbConnectionFactory>()
       .SingleInstance();

3. 使用示例

public class YourDataService
{
    private readonly IDbConnectionFactory _connectionFactory;

    // 注入工厂
    public YourDataService(IDbConnectionFactory connectionFactory)
    {
        _connectionFactory = connectionFactory;
    }

    public async Task ParallelQueryDemo()
    {
        // 每个并行任务独立获取连接
        var task1 = Task.Run(async () =>
        {
            using var conn = _connectionFactory.Create();
            return await conn.QueryAsync<EntityA>("SELECT * FROM TableA");
        });

        var task2 = Task.Run(async () =>
        {
            using var conn = _connectionFactory.Create();
            return await conn.QueryAsync<EntityB>("SELECT * FROM TableB");
        });

        await Task.WhenAll(task1, task2);
        // 处理查询结果
    }
}

方案二:Autofac委托工厂(无额外类定义,适合简单场景)

不需要额外定义工厂接口,直接注册委托类型的工厂:

// 1. 注册IDbConnection为瞬时模式,每次请求都返回新实例
builder.Register<IDbConnection>(c => new SqlConnection(_connectionString))
       .InstancePerDependency();

// 2. 注册连接创建委托作为工厂
builder.Register<Func<IDbConnection>>(c =>
{
    var context = c.Resolve<IComponentContext>();
    return () => context.Resolve<IDbConnection>();
});

使用时直接注入Func<IDbConnection>即可:

public class YourDataService
{
    private readonly Func<IDbConnection> _connFactory;

    public YourDataService(Func<IDbConnection> connFactory)
    {
        _connFactory = connFactory;
    }

    // 后续使用逻辑和方案一完全一致,调用_connFactory()获取新连接
}
注意事项
  • 每次从工厂获取的连接用完后要及时释放,建议配合using语句自动释放,避免连接池泄漏
  • 同一事务内的操作需要复用同一个连接,不要在事务范围内多次调用工厂创建新连接,避免触发不必要的分布式事务
  • 如果需要支持多种数据库类型,扩展自定义工厂接口的实现即可,适配性更强

内容的提问来源于stack exchange,提问作者DiPix

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 14:15:03