Dapper设置buffered为false时报错The ConnectionString property has not been initialized
异常触发原因
Dapper的buffered参数控制查询结果的加载行为:
buffered: true(默认值):调用Query方法时会立即执行查询,将所有结果加载到内存中的集合后再返回,数据库操作在方法返回前就已完成。buffered: false:返回的是延迟枚举的IEnumerable<T>,查询不会在Query调用时触发,而是等到第一次遍历返回结果时才真正执行数据库请求。
你原有代码中将IDbConnection放在using块中管理,调用Query方法后直接返回延迟枚举对象,此时using块生命周期结束,数据库连接被自动释放。等到上层代码遍历结果触发实际查询时,连接已经被销毁,对应的连接字符串属性处于未初始化状态,就会抛出该异常。
移除buffered参数后使用默认的true配置,查询在using块内就完成了结果加载,后续使用的是内存中的数据,不受连接释放的影响,因此运行正常。
非缓冲查询(buffered: false)的正确处理方式
使用buffered: false的核心前提是:数据库连接的生命周期必须覆盖整个结果集的遍历周期,常见的两种实现方案如下:
- 方案1:将连接生命周期交给调用方管理,方法内部不释放连接
// 调整方法签名,直接接收已初始化的数据库连接 public IEnumerable<T> GetAll<T>(string sql, DynamicParameters parameters, IDbConnection db, CommandType commandType = CommandType.StoredProcedure) { return db.Query<T>(sql, parameters, commandType: commandType, commandTimeout: COMMAND_TIMEOUT, buffered: false); } // 调用方示例 using IDbConnection db = new SqlConnection(yourConnectionString); db.Open(); // 遍历过程中连接保持存活 foreach (var item in GetAll<YourEntity>(sql, param, db)) { // 单条数据处理逻辑 } // 遍历完成后using自动释放连接
- 方案2:方法内部管理连接,同时在方法内部完成所有结果的遍历处理
如果不想把连接暴露给上层,可以传入数据处理委托,保证遍历完成后再释放连接:
public void ProcessAll<T>(string sql, DynamicParameters parameters, string connectionString, Action<T> itemHandler, CommandType commandType = CommandType.StoredProcedure) { using IDbConnection db = new SqlConnection(connectionString); db.Open(); // 遍历完成前连接不会被释放 foreach (var item in db.Query<T>(sql, parameters, commandType: commandType, commandTimeout: COMMAND_TIMEOUT, buffered: false)) { itemHandler(item); } }
内容的提问来源于stack exchange,提问作者lijevosmetalo
相关产品推荐
相关产品推荐

