如何在AutoMapper 3和Entity Framework中将整数映射为字符串

4

我正在尝试使用AutoMapper 3将具有整数属性的类投影到具有字符串属性的另一个类中。

当执行查询时,我会收到以下异常:

System.NotSupportedException: LINQ to Entities不认识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 Entities中工作? 或者是否有其他方法可以使投影与Linq to Entities一起工作?


SelectListItem.Value 不能是整数吗? - Gert Arnold
我也曾经考虑过同样的问题,但在这种情况下似乎行不通。不过我找到了一个解决方案并回答了这个问题。 - Elie
2个回答

4
解决方案是使用 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));

    }
}

1
不错!也许最好提到这适用于 Project().To() 语法,因为这样映射将作为表达式执行并转换为 SQL。使用 Mapper.Map 将无法实现此功能。 - Gert Arnold

2
我会把这个答案留在这里,以防其他人遇到和我一样的问题。 当前被接受的答案存在一个问题,如果你正在使用客户端验证帮助程序的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);
        }
    }
}

然后在 Automapper 配置文件中,我会这样映射这些项:
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属性的正确值,而不带有尾随空格。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接