ASP.NET Core中Dapper映射SQL Server自定义列名异常问题
问题原因
Dapper默认按列名与属性名完全匹配的规则映射字段,你SQL中[a0].[Id] AS [EntityChangeId]的列名是EntityChangeId,但HistoricalChangeDto继承的EntityDto中对应的属性是Id,名称不匹配导致映射失败;而ChangeTime列名与属性名一致,所以映射成功。
解决方案
方案1:修改SQL别名(最直接)
把SQL中[a0].[Id] AS [EntityChangeId]改为[a0].[Id] AS [Id],同时调整splitOn参数,让Dapper正确识别对象分割点:
修改后的SQL片段:
[a0].[Id] AS [Id], [a0].ChangeTime, [a2].[Id],
修改后的Dapper代码:
var assessmentChangeMetadataQueryResult = await connection.QueryAsync<ChangeMetadata, HistoricalChangeDto, User, ChangeMetadata>(assessmentChangeMetadataQuery, (changeMetadata, historicalChange, user) => { changeMetadata.User = user; changeMetadata.Change = historicalChange; return changeMetadata; }, splitOn: "Id,Id");
splitOn: "Id,Id"表示:
- 第一个
Id是HistoricalChangeDto对象的起始列 - 第二个
Id是User对象的起始列
方案2:用特性标记属性映射
在EntityDto的Id属性上添加[Column]特性,指定对应的数据库列名:
using System.ComponentModel.DataAnnotations.Schema; public class EntityDto { [Column("EntityChangeId")] public long Id { get; set; } }
Dapper会自动识别该特性,将EntityChangeId列映射到Id属性,无需修改SQL和splitOn参数。
方案3:手动在映射回调中赋值
给ChangeMetadata添加临时属性接收EntityChangeId,然后在回调中手动赋值给HistoricalChangeDto.Id:
- 修改
ChangeMetadata类:
private class ChangeMetadata { public long SetId { get; set; } public string EntityId { get; set; } public string EntityType { get; set; } public User User { get; set; } public EntityChangeType EntityChangeType { get; set; } public HistoricalChangeDto Change { get; set; } // 临时属性,用于接收SQL返回的EntityChangeId public long EntityChangeId { get; set; } }
- 调整回调逻辑:
var assessmentChangeMetadataQueryResult = await connection.QueryAsync<ChangeMetadata, HistoricalChangeDto, User, ChangeMetadata>(assessmentChangeMetadataQuery, (changeMetadata, historicalChange, user) => { changeMetadata.User = user; // 手动将临时属性的值赋值给HistoricalChangeDto的Id historicalChange.Id = changeMetadata.EntityChangeId; changeMetadata.Change = historicalChange; return changeMetadata; }, splitOn: "EntityChangeId,Id");
内容的提问来源于stack exchange,提问作者San Jaisy
相关产品推荐
相关产品推荐

