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

如何使用Dapper泛型获取存储过程的所有输出参数

解决Dapper存储过程输出参数自动映射的问题

要实现不暴露Dapper类型的前提下自动映射输出参数,核心是通过反射调用DynamicParameters的泛型Get方法,绕过C#泛型参数必须为编译时常量的限制。以下是修改后的可行实现:

修改后的关键代码段

在执行存储过程后的赋值环节,替换你原来的两种尝试:

if (outputParameters != null)
{
    var getMethod = typeof(DynamicParameters).GetMethod("Get", new Type[] { typeof(string) });
    foreach (PropertyInfo prop in outputParameters.GetType().GetProperties())
    {
        // 通过反射创建泛型版本的Get方法
        var genericGetMethod = getMethod.MakeGenericMethod(prop.PropertyType);
        // 调用Get方法获取输出参数值
        var value = genericGetMethod.Invoke(dynamicParameters, new object[] { prop.Name });
        // 将值赋值给outputParameters的对应属性
        prop.SetValue(outputParameters, value);
    }
}

关键说明

  1. 反射调用泛型方法:通过typeof(DynamicParameters).GetMethod获取Get<T>的非泛型方法定义,再用MakeGenericMethod传入属性的运行时类型,创建对应泛型版本的方法实例,最后用Invoke执行获取值。
  2. 参数名匹配:确保Add参数时用的是属性名(prop.Name),获取时直接传相同的名称即可,无需额外加@,Dapper内部会自动处理SQL参数的命名规则。
  3. 类型映射正确性:你的GetDbType方法必须正确将C#类型映射到对应的SQL DbType,否则输出参数可能无法正确赋值(比如字符串类型未指定长度、数值类型不匹配等)。

完整的CallProcedure方法示例

public void CallProcedure<I, O>(
    string storedProcedure,
    I inputParameters,
    O outputParameters,
    string connectionId = "Default")
{
    using IDbConnection connection = new SqlConnection(_config.GetConnectionString(connectionId));

    var dynamicParameters = new DynamicParameters();

    if (inputParameters != null)
        dynamicParameters.AddDynamicParams(inputParameters);

    if (outputParameters != null)
    {
        foreach (PropertyInfo prop in outputParameters.GetType().GetProperties())
        {
            dynamicParameters.Add(
                prop.Name,
                prop.GetValue(outputParameters),
                GetDbType(prop.PropertyType),
                ParameterDirection.Output);
        }
    }

    connection.Execute(storedProcedure, dynamicParameters, commandType: CommandType.StoredProcedure);

    if (outputParameters != null)
    {
        var getMethod = typeof(DynamicParameters).GetMethod("Get", new Type[] { typeof(string) });
        foreach (PropertyInfo prop in outputParameters.GetType().GetProperties())
        {
            var genericGetMethod = getMethod.MakeGenericMethod(prop.PropertyType);
            var value = genericGetMethod.Invoke(dynamicParameters, new object[] { prop.Name });
            prop.SetValue(outputParameters, value);
        }
    }
}

额外注意事项

  • 确保outputParameters的属性是可写的(即有set访问器),否则SetValue会失败。
  • 如果存储过程的输出参数允许为NULL,对应的C#属性应使用可空类型(如int?、string等),避免赋值时出现类型转换异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 15:09:22