AutoMapper映射JSON字符串到IEnumerable<string>时出现类型映射错误
问题:AutoMapper映射JSON字符串到IEnumerable失败的原因与解决方法
背景信息
领域模型
public class UserRoles : AggregateRoot<Guid> { public string Email { get; private set; } public IEnumerable<string> Roles { get; private set; } public UserRoles(Guid id, string email, IEnumerable<string> roles) : base(id) { Email = email; Roles = roles; } }
数据库实体(PostgreSQL jsonb存储)
角色信息在PostgreSQL中以jsonb类型存储为JSON字符串,对应的数据库实体:
public class UserRolesEntity { public Guid Id { get; set; } public string Email { get; set; } = null!; public string Roles { get; set; } = null!; }
数据库中Roles字段的存储示例:
["administrator", "engineer", "manager"]
仓储实现(EF Core + ABP IObjectMapper)
使用EntityFrameworkCore操作数据库,通过ABP框架的IObjectMapper(底层基于AutoMapper)实现数据库实体到领域模型的转换:
public class UserRolesRepository : IUserRolesRepository { private readonly IamDbContext _iamDbContext; private readonly IObjectMapper _objectMapper; public UserRolesRepository(...) {...} public async Task<UserRoles?> GetByEmailAsync(string email, CancellationToken...) { var dbEntity = await _iamDbContext.UserRolesList .SingleOrDefaultAsync(x => x.Email == email, cancellationToken); if (dbEntity == null) { return null; } return _objectMapper.Map<UserRolesEntity, UserRoles>(dbEntity); } }
AutoMapper映射配置
配置值解析器将JSON字符串反序列化为IEnumerable<string>:
public class DbEntityToDomainModelProfile : Profile { public DbEntityToDomainModelProfile() { CreateMap<UserRolesEntity, UserRoles>() .ForMember(dest => dest.Roles, opt => opt.MapFrom<JsonStringToUserRolesResolver>()) .Ignore(dest => dest.ConcurrencyStamp) .Ignore(dest => dest.ExtraProperties) .DisableCtorValidation(); } } public class JsonStringToUserRolesResolver : IValueResolver<UserRolesEntity, UserRoles, IEnumerable<string>> { public IEnumerable<string> Resolve(UserRolesEntity source, UserRoles dest, IEnumerable<string> destMember, ResolutionContext context) { // System.Text.Json var userRoles = JsonSerializer.Deserialize<IEnumerable<string>>(source.Roles); if (userRoles == null) { return Enumerable.Empty<string>(); } return userRoles; } }
问题现象
运行时抛出以下异常:
AutoMapper.AutoMapperMappingException: Missing type map configuration or unsupported mapping. Mapping types: String -> IEnumerable`1 System.String -> System.Collections.Generic.IEnumerable`1
临时解决方法
修改UserRoles领域模型,添加私有无参构造函数,并将构造函数中的roles参数重命名为roleList后,问题消失:
public class UserRoles : AggregateRoot<Guid> { ... private UserRoles() { } public UserRoles(Guid id, string email, IEnumerable<string> roleList) : base(id) { Email = email; Roles = roleList; } }
需求
请解释该错误的根本原因,并提供符合领域驱动设计规范的正确解决方式。
内容的提问来源于stack exchange,提问作者David Liang
相关产品推荐
相关产品推荐

