Dapper本身的设计定位是轻量高效的ORM,核心能力是完成实体对象和数据库查询结果的直接映射,并没有内置直接返回DataSet的方法。如果项目中需要基于Dapper获取DataSet,可以通过Dapper查询得到原始数据后,结合ADO.NET的相关组件手动完成DataSet的填充。

Dapper填充DataSet的核心思路
要实现Dapper返回DataSet,核心逻辑分为两步:首先使用Dapper执行查询,获取到IDataReader类型的查询结果;然后借助ADO.NET的DataAdapter组件,将IDataReader中的数据填充到DataSet中。整个流程不需要额外引入复杂的依赖,仅需要基础的ADO.NET组件支持即可完成。
单结果集填充DataSet的实现
当执行的查询只返回一个结果集时,填充逻辑比较简单,示例代码如下:
using System.Data;
using System.Data.SqlClient;
using Dapper;
public class DapperDataSetHelper
{
private readonly string _connectionString;
public DapperDataSetHelper(string connectionString)
{
_connectionString = connectionString;
}
// 单结果集查询填充DataSet
public DataSet QueryToDataSet(string sql, object param = null)
{
DataSet dataSet = new DataSet();
using (IDbConnection connection = new SqlConnection(_connectionString))
{
// 执行Dapper查询,获取IDataReader
IDataReader dataReader = connection.ExecuteReader(sql, param);
// 使用DataAdapter填充DataSet
using (IDataAdapter adapter = new SqlDataAdapter())
{
// 通过反射设置DataAdapter的SelectCommand的Reader属性
var selectCommandType = typeof(SqlDataAdapter).GetProperty("SelectCommand");
var selectCommand = selectCommandType.GetValue(adapter);
var readerProperty = selectCommand.GetType().GetProperty("Reader");
readerProperty.SetValue(selectCommand, dataReader);
adapter.Fill(dataSet);
}
}
return dataSet;
}
}
上述代码中,首先通过Dapper的ExecuteReader方法获取查询返回的IDataReader对象,然后创建SqlDataAdapter实例,将IDataReader赋值给适配器的查询命令的Reader属性,最后调用Fill方法完成DataSet的填充。
多结果集填充DataSet的实现
如果执行的查询返回多个结果集,比如一次性查询多张表的数据,需要为每个结果集创建对应的DataTable,再依次添加到DataSet中,示例如下:
using System.Data;
using System.Data.SqlClient;
using Dapper;
public DataSet QueryMultiResultToDataSet(string sql, object param = null)
{
DataSet dataSet = new DataSet();
using (IDbConnection connection = new SqlConnection(_connectionString))
{
// 执行查询获取多结果集的IDataReader
IDataReader dataReader = connection.ExecuteReader(sql, param);
int tableIndex = 0;
do
{
// 为每个结果集创建DataTable
DataTable dataTable = new DataTable();
dataTable.TableName = $"Table{tableIndex}";
// 加载当前结果集的数据
dataTable.Load(dataReader);
// 将DataTable添加到DataSet
dataSet.Tables.Add(dataTable);
tableIndex++;
} while (!dataReader.IsClosed && !dataReader.NextResult());
}
return dataSet;
}
这里使用do-while循环遍历所有结果集,通过IDataReader的NextResult方法切换到下一个结果集,直到所有结果集都处理完成,每个结果集对应DataSet中的一个DataTable。
注意事项
- 使用完成后及时释放
IDataReader和数据库连接,避免资源泄露,上述示例中都通过using语句完成了自动释放。 - 如果查询参数包含特殊字符或者需要防止SQL注入,一定要使用参数化查询,不要直接拼接SQL字符串,Dapper的参数化查询会自动处理参数转义。
- 填充完成后如果需要操作DataSet中的数据,注意DataTable的列类型会和数据库返回的字段类型自动匹配,不需要手动做类型转换。