如何在仓储项目中复用.NET Aspire配置的SqlConnection实例?
问题
基于.NET 8和Aspire 8的Aspire应用已在AppHost中配置了SQL Server容器。Web应用的Program.cs中通过builder.AddSqlServerClient("mySqlServer")将SqlConnection工厂注册到DI容器,可通过DI获取作用域内的SqlConnection实例。
现在为了分离关注点,Web项目引入了基于Dapper的数据仓储项目,并已通过DI注册:
builder.Services.AddScoped<IDataRepository, DataRepository>();
当前仓储是通过环境变量的连接字符串创建SqlConnection,希望复用Aspire ServiceDefaults配置好的SqlConnection实例,如何将Web项目DI容器中由AddSqlServerClient配置的SqlConnection传递给作用域内的IDataRepository?
解决方案
完全可以复用Aspire配置好的SqlConnection实例,核心是通过构造函数注入让仓储获取DI容器中的SqlConnection,具体实现如下:
1. 修改仓储类的构造函数
让DataRepository接收SqlConnection作为构造参数,替换原来通过环境变量创建连接的逻辑:
public class DataRepository : IDataRepository { private readonly SqlConnection _dbConnection; // 构造函数注入SqlConnection public DataRepository(SqlConnection dbConnection) { _dbConnection = dbConnection; } // 后续Dapper操作直接使用_dbConnection即可 public async Task<MyEntity> GetEntityById(int id) { return await _dbConnection.QueryFirstOrDefaultAsync<MyEntity>( "SELECT * FROM MyEntities WHERE Id = @Id", new { Id = id }); } }
2. 确保DI注册的正确性
因为AddSqlServerClient("mySqlServer")已经将SqlConnection注册为作用域服务(Aspire默认配置),而IDataRepository也是作用域服务,所以直接保留原有的仓储注册代码即可:
builder.Services.AddScoped<IDataRepository, DataRepository>();
DI容器会自动在每个作用域中,将配置好的SqlConnection实例注入到DataRepository中。
额外说明
如果需要更灵活的控制(比如需要根据不同场景获取连接),也可以注入ISqlConnectionFactory(由AddSqlServerClient自动注册),然后在仓储中按需创建连接:
public class DataRepository : IDataRepository { private readonly ISqlConnectionFactory _connectionFactory; public DataRepository(ISqlConnectionFactory connectionFactory) { _connectionFactory = connectionFactory; } public async Task<MyEntity> GetEntityById(int id) { using var connection = await _connectionFactory.CreateConnectionAsync(); return await connection.QueryFirstOrDefaultAsync<MyEntity>( "SELECT * FROM MyEntities WHERE Id = @Id", new { Id = id }); } }
这种方式适合需要手动管理连接生命周期的场景,同样能复用Aspire配置的连接字符串和相关设置。
内容的提问来源于stack exchange,提问作者Boggin

