如何使用自动映射器 3 和实体框架将整数映射到字符串

本文关键字:映射 框架 整数 字符串 实体 何使用 | 更新日期: 2023-09-27 18:34:13

我正在尝试使用AutoMapper 3将具有Integer属性的类投影到具有String属性的另一个类。

执行查询时,我得到以下异常:

System.NotSupportedException:LINQ to Entities 无法识别方法"System.String ToString()"方法,并且此方法无法转换为存储表达式。

以下是代码的相关部分:

public partial class Lookup
{
    public int LookupId { get; set; }
    public int LookupTypeId { get; set; }
    public string Value { get; set; }
    public int SequencialOrder { get; set; }
    public virtual LookupType LookupType { get; set; }
}
public class LookupProfile : Profile
{
    protected override void Configure()
    {
        CreateMap<Lookup, SelectListItem>()
            .ForMember(dest => dest.Value, opt => opt.MapFrom(src => src.LookupId.ToString()))
            .ForMember(dest => dest.Text, opt => opt.MapFrom(src => src.Value));
    }
}

查询如下所示:

Provinces = _db.Lookups.Project().To<SelectListItem>().ToList()

问题:

有没有办法将 LookupProfile 配置为执行正确的映射,并且仍然可以在 Linq To 实体中工作?或者有没有另一种方法可以使投影与 Linq to Entities 一起使用?

如何使用自动映射器 3 和实体框架将整数映射到字符串

解决方案是使用 SqlFunctions.StringConvert 函数。

以下是使一切正常工作的修改后的配置文件代码:

public class LookupProfile : Profile
{
    protected override void Configure()
    {
        CreateMap<Lookup, SelectListItem>()
            .ForMember(dest => dest.Value, opt => opt.MapFrom(src => SqlFunctions.StringConvert((double)src.LookupId)))
            .ForMember(dest => dest.Text, opt => opt.MapFrom(src => src.Value));
    }
}

我会把这个答案留在这里,以防其他人偶然发现我遇到的相同问题。

当前接受的答案的一个问题是,如果你在通过帮助程序使用客户端验证的 ASP.NET MVC 项目上,你将收到 ID 字段的验证错误(如果它是一个数字): The field [field] must be a number. 发生这种情况是因为 SqlFunctions.StringConvert 的结果返回一个包含多个前导空格的字符串,因此不显眼的验证器不会将其视为数字。

我自己解决这个问题的方法是创建一个泛型SelectListItem<T>类,该类继承自SelectListItem,隐藏原始Value属性并实现自己的Value setter:

public class SelectListItem<T> : SelectListItem
{
    public new T Value {
        set {
            base.Value = value.ToString();
        }
        // Kind of a hack that I had to add 
        // otherwise the code won't compile
        get {
            return default(T);
        }
    }
}

然后在自动映射器配置文件上,我将映射如下项目:

public class LookupProfile : Profile
{
    protected override void Configure()
    {
        //Use whatever datatype is appropriate: decimal, int, short, etc
        CreateMap<Lookup, SelectListItem<int>>()
            .ForMember(dest => dest.Value, opt => opt.MapFrom(src => src.LookupId))
            .ForMember(dest => dest.Text, opt => opt.MapFrom(src => src.Value));
    }
}

最后,在服务层,我将实体映射到泛型类并返回一个IEnumerable<SelectListItem>

public IEnumerable<SelectListItem> GetList() {
    return _db.Lookups.Project().To<SelectListItem<int>>().ToList();
}

这样,您将获得 Value 属性的正确值,而不带尾随空格。