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

如何从Dapper动态对象(查询结果)中获取属性值

解决Dapper多映射中获取对象属性值的问题

核心问题是你当前只获取了PropertyInfo对象,没有调用GetValue方法提取实际属性值,同时可以通过更简洁的方式避免复杂反射:

1. 修复反射代码(临时方案)

将你的反射代码修改为调用GetValue获取实际值,同时添加空值保护:

// 示例:获取CERTIFYING_ACTUARY_ID的值
INTERNAL_USER_NUMBER = (int?)objects[4].GetType().GetProperty("CERTIFYING_ACTUARY_ID")?.GetValue(objects[4]),
FIRST_NAME = (string?)objects[4].GetType().GetProperty("CERTIFYING_ACTUARY_FIRST_NAME")?.GetValue(objects[4]),
LAST_NAME = (string?)objects[4].GetType().GetProperty("CERTIFYING_ACTUARY_LAST_NAME")?.GetValue(objects[4])

?.运算符用于避免属性不存在时出现空引用异常。

2. 使用Dynamic类型(简洁方案)

将objects[4]转换为dynamic类型,直接访问属性,省去反射代码:

map: (objects) => {
    var certificationReview = (ARMS_API.Models.CertificationReview)objects[0];
    certificationReview.STATE = (State)objects[1];
    certificationReview.STATE.PROGRAMS.Add((ARMS_API.Models.Program)objects[2]);
    certificationReview.ACTUARIAL_FIRM = (ActuarialFirm)objects[3];
    
    // 转换为dynamic类型
    var userData = (dynamic)objects[4];

    certificationReview.ACTUARIAL_FIRM.CERTIFYING_ACTUARY.Add(
        new User {
            INTERNAL_USER_NUMBER = userData.CERTIFYING_ACTUARY_ID,
            FIRST_NAME = userData.CERTIFYING_ACTUARY_FIRST_NAME,
            LAST_NAME = userData.CERTIFYING_ACTUARY_LAST_NAME
        });
    certificationReview.PRIMARY_REVIEWER = 
        new User {
            INTERNAL_USER_NUMBER = userData.PRIMARY_ACTUARY_ID,
            FIRST_NAME = userData.PRIMARY_ACTUARY_FIRST_NAME,
            LAST_NAME = userData.PRIMARY_ACTUARY_LAST_NAME
        };
    // 其他User对象同理...
    
    return certificationReview;
}

3. 创建DTO类(最佳实践,类型安全)

定义一个包含所有用户相关字段的DTO类,替换typeof(object),实现强类型映射:

// 定义DTO类
public class UserRelatedData
{
    public int? CERTIFYING_ACTUARY_ID { get; set; }
    public string CERTIFYING_ACTUARY_FIRST_NAME { get; set; }
    public string CERTIFYING_ACTUARY_LAST_NAME { get; set; }
    public int? PRIMARY_ACTUARY_ID { get; set; }
    public string PRIMARY_ACTUARY_FIRST_NAME { get; set; }
    public string PRIMARY_ACTUARY_LAST_NAME { get; set; }
    public int? SECONDARY_ACTUARY_ID { get; set; }
    public string SECONDARY_ACTUARY_FIRST_NAME { get; set; }
    public string SECONDARY_ACTUARY_LAST_NAME { get; set; }
    public int? DMCP_ANALYST_ID { get; set; }
    public string DMCP_ANALYST_FIRST_NAME { get; set; }
    public string DMCP_ANALYST_LAST_NAME { get; set; }
}

然后修改QueryAsync的types参数和映射代码:

var certificationReviews = await connection.QueryAsync<ARMS_API.Models.CertificationReview>(
    "select * from dbo.A2F_DMCP_0005_BrowseTest()", 
    types: new[] { 
        typeof(ARMS_API.Models.CertificationReview), 
        typeof(State), 
        typeof(ARMS_API.Models.Program), 
        typeof(ActuarialFirm), 
        typeof(UserRelatedData), // 替换原typeof(object)
        typeof(object), 
        typeof(object) , 
        typeof(object)
    }, 
    map: (objects) => {
        var certificationReview = (ARMS_API.Models.CertificationReview)objects[0];
        certificationReview.STATE = (State)objects[1];
        certificationReview.STATE.PROGRAMS.Add((ARMS_API.Models.Program)objects[2]);
        certificationReview.ACTUARIAL_FIRM = (ActuarialFirm)objects[3];
        
        // 强类型转换
        var userData = (UserRelatedData)objects[4];

        certificationReview.ACTUARIAL_FIRM.CERTIFYING_ACTUARY.Add(
            new User {
                INTERNAL_USER_NUMBER = userData.CERTIFYING_ACTUARY_ID,
                FIRST_NAME = userData.CERTIFYING_ACTUARY_FIRST_NAME,
                LAST_NAME = userData.CERTIFYING_ACTUARY_LAST_NAME
            });
        // 其他User对象同理...
        
        return certificationReview;
    },
    splitOn: "STATE_ID,PROGRAM_DD,ACTUARIAL_FIRM_DD,CERTIFYING_ACTUARY_ID,PRIMARY_ACTUARY_ID,SECONDARY_ACTUARY_ID,DMCP_ANALYST_ID");

另外需确保splitOn参数中的字段顺序与types数组的类型顺序匹配,每个字段对应下一个类型的起始列,避免映射错位。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 12:34:53