【问题标题】:AutoMapperMappingException Mapping types: Double -> DoubleAutoMapperMappingException 映射类型:Double -> Double
【发布时间】:2012-11-29 08:19:01
【问题描述】:

当我尝试在我的应用程序中调用 Mapper.Map 时出现以下异常:

AutoMapper.AutoMapperMappingException. 

Mapping types:
Double -> Double
System.Double -> System.Double

Destination path:
Address.Latitude

Source value:
42.250287

   System.InvalidCastException. Unable to cast object of type 'Acme.Order' to type 'Acme.Address'.

除了明显的错误表明它无法映射相同类型(以及原始类型)的对象之外,事实是我从不从“Acme.Order”类型映射到“Acme.Order”类型。地址”!

这是实际使用的调用:

var order = Mapper.Map<IDataRecord, Order>(theDataReader);

我的对象模型如下所示:

public class Order
{
    public Address Address { get; set; }
    public Int32 Number { get; set; }
    public PhoneNumber PhoneNumber { get; set; }
}

public class Address
{
    public String City { get; set; }
    public Double Latitude { get; set; }
    public Double Longitude { get; set; }
    public Int32 Number { get; set; }
    public String PostalCode { get; set; }
    public String State { get; set; }
    public String Street { get; set; }
}

public class PhoneNumber
{
    public String Extension { get; set; }
    public String Number { get; set; }
}

我的应用程序中定义了以下配置:

CreateMap<IDataRecord, Address>()
.ForMember(target => target.Latitude, opt => opt.MapFrom(record => GetDoubleFrom(record, "Latitude", 0)))
.ForMember(target => target.Longitude, opt => opt.MapFrom(record => GetDoubleFrom(record, "Longitude", 0)))
;
CreateMap<IDataRecord, PhoneNumber>()
.ForMember(target => target.Extension, opt => opt.MapFrom(record => GetStringFrom(record, "Extension", String.Empty)))
.ForMember(target => target.Number, opt => opt.MapFrom(record => GetStringFrom(record, "PhoneNumber", String.Empty)))
;
CreateMap<IDataRecord, Order>()
.ForMember(target => target.Address, opt => opt.ResolveUsing(record => Mapper.Map<IDataRecord, Address>(record)))
.ForMember(target => target.PhoneNumber, opt => opt.ResolveUsing(record => Mapper.Map<IDataRecord, PhoneNumber>(record)))
;

使用这些辅助方法:

private Double GetDoubleFrom(IDataRecord record, String name, Double defaultValue)
{
    return (record.Contains(name) && !record.IsDbNull(name)) ? record.GetDouble(name) : defaultValue;
}

private String GetStringFrom(IDataRecord record, String name, String defaultValue)
{
    return (record.Contains(name) && !record.IsDbNull(name)) ? record.GetString(name) : defaultValue;
}

(我在 IDataRecord 上有扩展方法,它们采用字段名称、获取序号并使用标准方法返回值,但为简洁起见,不会显示它们。)

这是否能说明导致失败的原因?

(顺便说一句,我正在使用 AutoMapper v2.1.267)

【问题讨论】:

    标签: automapper automapper-2


    【解决方案1】:

    我无法直接重新创建它,因为它缺少一些信息(例如IDataRecord 接口的具体类,theDataReader 的内容等)。但是,第一个检查是确保您的映射是正确的。你用AssertConfigurationIsValid测试它吗?

    例如,如果您有以下 AutoMapper 配置文件:

    public class MyProfile : Profile
    {
        public override string ProfileName
        {
            get
            {
                return "MyProfile";
            }
        }
    
        protected override void Configure()
        {
            CreateMap<IDataRecord, Address>()
                .ForMember(
                    target => target.Latitude,
                    opt => opt.MapFrom(
                        record => GetDoubleFrom(record, "Latitude", 0)))
                .ForMember(
                    target => target.Longitude,
                    opt => opt.MapFrom(
                        record => GetDoubleFrom(record, "Longitude", 0)));
            CreateMap<IDataRecord, PhoneNumber>()
                .ForMember(
                    target => target.Extension,
                    opt => opt.MapFrom(
                        record => GetStringFrom(record, "Extension", string.Empty)))
                .ForMember(
                    target => target.Number,
                    opt => opt.MapFrom(
                        record => GetStringFrom(record, "PhoneNumber", string.Empty)));
            CreateMap<IDataRecord, Order>()
                .ForMember(
                    target => target.Address,
                    opt => opt.ResolveUsing(
                        record => Mapper.Map<IDataRecord, Address>(record)))
                .ForMember(
                    target => target.PhoneNumber,
                    opt => opt.ResolveUsing(
                        record => Mapper.Map<IDataRecord, PhoneNumber>(record)));
        }
    }
    

    这个单元测试会通过吗?

    [Test]
    public void AutoMapper_Configuration_IsValid()
    {
        Mapper.Initialize(m => m.AddProfile<MyProfile>());
        Mapper.AssertConfigurationIsValid();
    }
    

    更新

    你可以试试

    CreateMap<IDataRecord, Order>()
        .ForMember(
            target => target.Address,
            opt => opt.MapFrom(record => Mapper.Map<IDataRecord, Address>(record)))
        .ForMember(
            target => target.PhoneNumber,
            opt => opt.MapFrom(record => Mapper.Map<IDataRecord, PhoneNumber>(record)));
    

    【讨论】:

    • IDataRecord 是 ADO.NET 的一部分,由所有 DataReader 类实现。
    • 是的,我们在运行时以及在我们的单元测试中使用 AssertConfigurationIsValid 并且它始终如一地通过。
    • 抱歉,是的,我知道IDataRecord 是什么,只是暗示我不知道如何针对这种特殊情况进行存根。
    • 肯定是个奇怪的错误。由于无法在本地重新创建它,我只能建议尝试升级到最新版本的 AutoMapper (2.2.0),和/或在 AutoMapper mailing list 上发布。
    • 还有什么建议我可以解决正在发生的事情吗?我的意思是,Mapper.Map 是一个黑盒子。我已经查看了源代码,但没有任何东西让我知道它在内部尝试做什么会导致这样一个令人费解的错误消息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-15
    相关资源
    最近更新 更多