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

能否用泛型集合替代多T泛型参数创建通用Dapper方法?

用灵活类型集合替代固定多泛型参数的Dapper多结果读取方法

你原来的代码确实实现了多泛型参数的方法,但固定的T1-T4限制了方法的灵活性——只能处理最多4种结果类型。要实现适配任意数量结果类型的通用方法,可以结合反射和Type数组来动态读取每个结果集,替代固定泛型参数的写法。

实现方案:动态读取任意数量的结果集

下面是一个通用方法,通过传入结果类型的数组,动态调用Dapper的Read<T>方法,返回对应类型的结果集合:

public static List<IEnumerable<object>> DapperMultiRead(string sql, params Type[] resultTypes)
{
    // 假设conString是你的数据库连接字符串
    using (var connection = new SqlConnection(conString))
    using (var multi = connection.QueryMultiple(sql, null))
    {
        var results = new List<IEnumerable<object>>();
        foreach (var type in resultTypes)
        {
            // 获取GridReader的泛型Read<T>方法
            var readMethod = typeof(SqlMapper.GridReader)
                .GetMethod("Read", Type.EmptyTypes)
                ?.MakeGenericMethod(type);
            
            if (readMethod == null)
            {
                results.Add(Enumerable.Empty<object>());
                continue;
            }

            // 调用Read<T>并转换为IEnumerable<object>
            var result = readMethod.Invoke(multi, null) as IEnumerable<object>;
            results.Add(result?.ToList() ?? Enumerable.Empty<object>());
        }
        return results;
    }
}

使用示例

调用时传入SQL语句和需要读取的结果类型即可,后续可以将结果转换为具体类型的列表:

// 读取两个不同类型的结果集
var results = DapperMultiRead(
    "Select * from InventoryMaster;Select * from OrderMaster",
    typeof(InventoryMaster),
    typeof(OrderMaster)
);

// 转换为具体类型的列表
var inventoryList = results[0].Cast<InventoryMaster>().ToList();
var orderList = results[1].Cast<OrderMaster>().ToList();

优缺点说明

  • 优点:完全适配任意数量的结果类型场景,不需要为每种数量的泛型参数写重载方法。
  • 缺点:使用了反射,相比直接写泛型方法有轻微的性能开销;返回结果需要手动转换为具体类型,失去了部分编译时类型安全。

替代方案:类型安全的重载方法

如果对性能和类型安全要求更高,可以针对常用的泛型参数数量写重载方法,比如:

// 2个结果类型的重载
public static (List<T1>, List<T2>) DapperMultiRead<T1, T2>(string sql)
{
    using (var connection = new SqlConnection(conString))
    using (var multi = connection.QueryMultiple(sql, null))
    {
        return (multi.Read<T1>().ToList(), multi.Read<T2>().ToList());
    }
}

// 3个结果类型的重载
public static (List<T1>, List<T2>, List<T3>) DapperMultiRead<T1, T2, T3>(string sql)
{
    using (var connection = new SqlConnection(conString))
    using (var multi = connection.QueryMultiple(sql, null))
    {
        return (multi.Read<T1>().ToList(), multi.Read<T2>().ToList(), multi.Read<T3>().ToList());
    }
}

这种方式没有反射开销,且编译时就能保证类型安全,但需要提前预设常用的泛型参数数量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 06:17:22