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

如何实现Dapper QueryMultipleAsync的泛型方法?当前实现报‘Parameter count mismatch.’错误

如何实现Dapper QueryMultipleAsync的泛型方法?当前实现报‘Parameter count mismatch.’错误

我帮你分析下这个问题哈,你遇到的「Parameter count mismatch.」错误,核心原因是通过反射调用Dapper的ReadAsync和ReadSingleAsync方法时,没有匹配到无参数的泛型重载版本,导致调用时参数不匹配。

错误根源

Dapper的SqlMapper.GridReader类中,ReadAsync和ReadSingleAsync都有多个重载(比如带CommandBehavior、commandTimeout参数的版本)。你当前的反射查找逻辑只过滤了方法名称和是否泛型,没限定参数数量,大概率拿到了带参数的重载,这时候用Invoke(multi, null)调用就会因为参数数量不符报错。

修正后的实现代码

下面是修复后的完整方法,我调整了反射查找方法的逻辑,同时加了方法缓存来提升性能:

// 缓存反射获取的方法,避免每次调用都重新查找
private static readonly MethodInfo _readAsyncGenericMethod = typeof(SqlMapper.GridReader)
    .GetMethods()
    .FirstOrDefault(m => m.Name == nameof(SqlMapper.GridReader.ReadAsync) &&
                         m.IsGenericMethod &&
                         m.GetParameters().Length == 0);

private static readonly MethodInfo _readSingleAsyncGenericMethod = typeof(SqlMapper.GridReader)
    .GetMethods()
    .FirstOrDefault(m => m.Name == nameof(SqlMapper.GridReader.ReadSingleAsync) &&
                         m.IsGenericMethod &&
                         m.GetParameters().Length == 0);

public async Task<List<object>> GetMultipleAsync<U>(string storedProcedure, U parameters, List<Type> types)
{
    var result = new List<object>();
    try
    {
        using (var multi = await _connection.QueryMultipleAsync(storedProcedure, parameters, commandType: CommandType.StoredProcedure, transaction: _transaction))
        {
            foreach (var type in types)
            {
                if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
                {
                    // 处理集合类型
                    var elementType = type.GetGenericArguments()[0];
                    var genericMethod = _readAsyncGenericMethod.MakeGenericMethod(elementType);
                    var task = (Task)genericMethod.Invoke(multi, null);
                    await task.ConfigureAwait(false);

                    var data = task.GetType().GetProperty("Result")?.GetValue(task);
                    if (data != null)
                    {
                        result.Add(data);
                    }
                }
                else
                {
                    // 处理单个对象类型
                    var genericMethod = _readSingleAsyncGenericMethod.MakeGenericMethod(type);
                    var task = (Task)genericMethod.Invoke(multi, null);
                    await task.ConfigureAwait(false);

                    var data = task.GetType().GetProperty("Result")?.GetValue(task);
                    if (data != null)
                    {
                        result.Add(data);
                    }
                }
            }
        }
    }
    catch (Exception ex)
    {
        // 这里可以添加你的异常处理逻辑,比如日志记录
        Console.WriteLine($"获取多数据集失败:{ex.Message}");
        throw; // 建议不要吞掉异常,上层可以根据需要处理
    }
    return result;
}

关键优化点说明

  1. 精准匹配无参数重载
    在查找ReadAsync和ReadSingleAsync方法时,增加了m.GetParameters().Length == 0的条件,确保拿到的是无参数的泛型重载,这样调用时传null就不会有参数不匹配的问题了。

  2. 缓存反射方法
    把反射获取到的方法实例缓存为静态字段,避免每次调用方法都重新遍历查找,大幅提升性能。

  3. 空值安全处理
    增加了?.空值判断,避免反射获取Result属性时出现空引用异常。

验证使用场景

你原来的调用方式完全可以正常工作:

var types = new List<Type>
{
    typeof(List<ModelA>),
    typeof(List<ModelB>),
    typeof(long)
};

var resultMultiple = await _dataAccess.GetMultipleAsync<DynamicParameters>(storedProcedure, parameters, types);

// 解析结果
var ListA = resultMultiple[0] as List<ModelA>;
var ListB = resultMultiple[1] as List<ModelB>;
var val = (long)resultMultiple[2];

备注:内容来源于stack exchange,提问作者SYED NAWAZ PRINCE

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 11:03:00