如何从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
相关产品推荐
相关产品推荐

