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

在C#中如何将数据库列转换为List<string>映射到模型属性

解决Dapper将JSON字符串映射为List属性的问题

问题场景

数据库表unit_properties的images列存储的是["a","b","c","d"]格式的JSON字符串。原本C#模型中UnitImages为string类型时,Dapper查询映射完全正常;但将该属性改为List<string>?类型后,无法自动完成映射,期望返回的JSON结构中unitImages是字符串数组形式:

[
  {
    "unitId": 1,
    "unitTitle": "1 Bedroom Studio",
    "unitDescription": "Fully renovated and move in ready apartments are available for rent...",
    "unitImages": [
        "a",
        "b",
        "c",
        "d"
       ],
    "unitAddress": "6876 86 Street Edmonton",
    "unitRooms": 1
  }
]

修改后的C#模型:

public class UnitProperty
{
    public long? UnitId { get; set; }
    public string? UnitTitle { get; set; }
    public string? UnitDescription { get; set; }
    public List<string>? UnitImages { get; set; } // 修改为List<string>类型
    public string? UnitAddress { get; set; }
    public int? UnitRooms { get; set; }
    public int? UnitBathrooms { get; set; }
    public int? UnitSquareMeters { get; set; }
    public bool? UnitHasParking { get; set; }
    public decimal? UnitPrice { get; set; }
    public int? UnitWalkScore { get; set; }
    public int? UnitTransitScore { get; set; }
    public int? UnitBikeScore { get; set; }
    public User? Agent { get; set; }
    public Category? Category { get; set; }
}

原控制器查询代码(原UnitImages为string时正常运行):

// GET: api/<UnitPropertyController>
[HttpGet("Units", Name = "GetUnits")]
public async Task<List<UnitProperty>> GetUnitsAsync([FromServices] MySqlConnection connection)
{
    string query = @"
    SELECT
        up.id as unitId,
        up.title as unitTitle,
        up.description as unitDescription,
        up.images as unitImages,
        up.address as unitAddress,
        up.rooms as unitRooms,
        up.bathrooms as unitBathrooms,
        up.square_meters as unitSquareMeters,
        up.has_parking as unitHasParking,
        up.price as unitPrice,
        up.walk_score as unitWalkScore,
        up.transit_score as unitTransitScore,
        up.bike_score as unitBikeScore,
        up.agent_id,
        up.category_id,

        c.id as categoryId,
        c.name as categoryName,
        c.image as categoryImage,

        u.id as userId,
        u.name as userName,
        u.image as userImage,
        u.email as userEmail,
        u.phone_number as userPhoneNumber,
        u.address as userAddress,
        u.description as userDescription,
        u.user_role as userRole

    FROM unit_properties up
    INNER JOIN categories c ON up.category_id = c.id
    INNER JOIN users u ON up.agent_id = u.id;
";

var multiQuery = await connection.QueryMultipleAsync(query);
var unitProperties = multiQuery.Read<UnitProperty, Category, User, UnitProperty>(
    (unitProperty, category, user) =>
    {
        unitProperty.Category = category;
        unitProperty.Agent = user;

        return unitProperty;
    },
    splitOn: "categoryId,userId"
);

List<UnitProperty> results = unitProperties.ToList();

return results;
}

解决方案

方案1:查询后手动反序列化

无需修改Dapper配置,在获取查询结果后,遍历每个对象完成JSON字符串到列表的转换:

List<UnitProperty> results = unitProperties.ToList();

foreach (var property in results)
{
    var jsonStr = property.UnitImages as string;
    if (!string.IsNullOrEmpty(jsonStr))
    {
        // 用System.Text.Json反序列化,若用Newtonsoft.Json则替换为JsonConvert.DeserializeObject
        property.UnitImages = System.Text.Json.JsonSerializer.Deserialize<List<string>>(jsonStr);
    }
}

return results;

方案2:注册Dapper自定义类型处理器

通过自定义类型处理器,让Dapper自动完成JSON字符串与List<string>的双向映射,一劳永逸:

  1. 定义类型处理器:
using Dapper;
using System.Text.Json;

public class StringListTypeHandler : SqlMapper.TypeHandler<List<string>>
{
    public override List<string> Parse(object value)
    {
        if (value == null || string.IsNullOrWhiteSpace(value.ToString()))
            return null;
            
        return JsonSerializer.Deserialize<List<string>>(value.ToString());
    }

    public override void SetValue(System.Data.IDbDataParameter parameter, List<string> value)
    {
        parameter.Value = value == null ? null : JsonSerializer.Serialize(value);
    }
}
  1. 在项目启动时注册处理器(比如Program.cs):
SqlMapper.AddTypeHandler(new StringListTypeHandler());
  1. 保持修改后的UnitProperty模型不变,原控制器代码无需任何改动,Dapper会自动完成映射。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 22:17:45