2010-01-12 12 views
6

Aggiornamento 1-13-10 Sono riuscito a trovare un po 'di successo utilizzando il seguente codice per la mappatura. In sostanza sto ignorando le proprietà che non hanno una mappatura e le mappano in seguito. Gradirei il feedback sul fatto che io vada o meno al riguardo nel modo migliore possibile. Inoltre, non sono sicuro su come procedere per testare questa mappatura. Ho avuto l'impressione che l'utilizzo di AutoMapper dovrebbe contribuire ad alleviare la noiosità del controllo di ogni proprietà.Eccezione mappatura personalizzata automapper

Ecco il mio nuovo codice:

Mapper.CreateMap<MoveEntity, MoveEntityDto>() 
      .ForMember(dest => dest.PrimaryOriginTransferee, opt => opt.Ignore()) 
      .ForMember(dest => dest.PrimaryDestinationTransferee, opt => opt.Ignore()) 
      .ForMember(dest => dest.Customer, opt => opt.Ignore()) 
      .ForMember(dest => dest.DestinationAddress, opt => opt.Ignore()) 
      .ForMember(dest => dest.OriginAddress, opt => opt.Ignore()) 
      .ForMember(dest => dest.Order, opt => opt.Ignore()) 
      .ForMember(dest => dest.Shipment, opt => opt.Ignore()) 
      .ForMember(dest => dest.SourceSystemName, opt => opt.Ignore()); 

     Mapper.CreateMap<ContactEntity, TransfereeEntityDto>(); 
     Mapper.CreateMap<CustomerEntity, CustomerEntityDto>(); 
     Mapper.CreateMap<AddressEntity, AddressEntityDto>(); 
     Mapper.CreateMap<OrderEntity, OrderEntityDto>() 
      .ForMember(dest => dest.OrderForwarding, opt => opt.Ignore()) 
      .ForMember(dest => dest.Forwarder, opt => opt.Ignore()); 
     Mapper.CreateMap<ShipmentEntity, ShipmentEntityDto>() 
      .ForMember(dest => dest.Services, opt => opt.Ignore()); 
     Mapper.CreateMap<ServiceEntity, ServiceEntityDto>() 
      .ForMember(dest => dest.ServiceTypeCode, opt => opt.Ignore()) //TODO: ServiceTypeCode not being mapped, should it? 
      .ForMember(dest => dest.SourceSystemName, opt => opt.MapFrom(src => Enum.GetName(typeof(SourceSystemName), src.SourceSystemName))); 
     Mapper.CreateMap<OrderForwardingEntity, OrderForwardingEntityDto>(); 


     Mapper.AssertConfigurationIsValid(); 


     MoveEntityDto moveEntityDto = Mapper.Map<MoveEntity, MoveEntityDto>(moveEntity); 
     moveEntityDto.PrimaryDestinationTransferee = Mapper.Map<ContactEntity, TransfereeEntityDto>(moveEntity.PrimaryDestinationTransferee); 
     moveEntityDto.PrimaryOriginTransferee = Mapper.Map<ContactEntity, TransfereeEntityDto>(moveEntity.PrimaryOriginTransferee); 
     moveEntityDto.Customer = Mapper.Map<CustomerEntity, CustomerEntityDto>(moveEntity.Customer); 
     moveEntityDto.DestinationAddress = Mapper.Map<AddressEntity, AddressEntityDto>(moveEntity.DestinationAddress); 
     moveEntityDto.OriginAddress = Mapper.Map<AddressEntity, AddressEntityDto>(moveEntity.OriginAddress); 
     moveEntityDto.Order = Mapper.Map<OrderEntity, OrderEntityDto>(moveEntity.Order); 
     moveEntityDto.Order.OrderForwarding = Mapper.Map<OrderForwardingEntity, OrderForwardingEntityDto>(moveEntity.Order.OrderForwarding); 
     //moveEntityDto.Order.Forwarder = Mapper.Map<ForwarderEntity, ForwarderEntityDto>(moveEntity.Order.Forwarder); //Apparently there is no forwarder entity for an Order 
     moveEntityDto.Shipment = Mapper.Map<ShipmentEntity, ShipmentEntityDto>(moveEntity.Shipment); 
     moveEntityDto.Shipment.Services = Mapper.Map<ServiceEntity[], ServiceEntityDto[]>(moveEntity.Shipment.ServiceEntities); 

originale del messaggio:

Sto tentando di usare automapper per la prima volta al fine di mappare da un oggetto Bussiness ad un DTO. Sono in esecuzione in problemi che non so come risolvere, tra cui la seguente eccezione:

AutoMapper.AutoMapperMappingException: Cercando di mappare Graebel.SP.BO.MoveEntity a Graebel.SOA.Contracts.DataContracts.SP. MoveEntity. eccezione di tipo 'AutoMapper.AutoMapperMappingException' stato gettato

Ecco il codice automapper che io sono in esecuzione:

public MoveEntityDto MapMoveEntityToMoveEntityDto(MoveEntity moveEntity) 
    { 
     Mapper.CreateMap<MoveEntity, MoveEntityDto>() 
      .ForMember(dest => dest.PrimaryOriginTransferee, opt => opt.MapFrom(src => src.PrimaryOriginTransferee)) 
      .ForMember(dest => dest.PrimaryDestinationTransferee,opt => opt.MapFrom(src => src.PrimaryDestinationTransferee)) 
      .ForMember(dest => dest.Customer, opt => opt.MapFrom(src => src.Customer)) 
      .ForMember(dest => dest.DestinationAddress, opt => opt.MapFrom(src => src.DestinationAddress)) 
      .ForMember(dest => dest.Order, opt => opt.MapFrom(src => src.Order)) 
      .ForMember(dest => dest.OriginAddress, opt => opt.MapFrom(src => src.OriginAddress)) 
      .ForMember(dest => dest.Shipment, opt => opt.MapFrom(src => src.Shipment)) 
      .ForMember(dest => dest.SourceSystemName, opt => opt.Ignore()); 

     Mapper.AssertConfigurationIsValid(); 
     MoveEntityDto moveEntityDto = Mapper.Map<MoveEntity, MoveEntityDto>(moveEntity); 

     return moveEntityDto; 
    } 

Ecco la DTO (MoveEntityDto) che sto tentando di mappare:

public class MoveEntityDto 
{  
    public bool IsOrderDetailPageModified { get; set; } 
    public bool IsRoutingPageModified { get; set; } 
    public bool IsServicePageModified { get; set; } 
    public bool IsContentAndContainerPageModified { get; set; } 
    public string FamilyRange { get; set; } 
    public string Office { get; set; } 
    public string ActivityType { get; set; } 
    public string ActivitySubject { get; set; } 
    public string ActivityNote { get; set; } 
    public TransfereeEntity PrimaryOriginTransferee { get; set; } 
    public TransfereeEntity PrimaryDestinationTransferee { get; set; } 
    public CustomerEntity Customer { get; set; } 
    public AddressEntity OriginAddress { get; set; } 
    public AddressEntity DestinationAddress { get; set; } 
    public OrderEntity Order { get; set; } 
    public ShipmentEntity Shipment { get; set; } 
    public string PortalId { get; set; } 
    public string SourceSystemId { get; set; } 
    public EnterpriseEnums.SourceSystemName SourceSystemName { get; set; } 

    public MoveEntity() 
    { 
     PrimaryOriginTransferee = new TransfereeEntity(); 
     PrimaryDestinationTransferee = new TransfereeEntity(); 
     Customer = new CustomerEntity(); 
     OriginAddress = new AddressEntity(); 
     DestinationAddress = new AddressEntity(); 
     Order = new OrderEntity(); 
     Shipment = new ShipmentEntity(); 
    } 

    public bool HasShipment() 
    { 
     if (Shipment.ExternalShipmentId > 0) 
     { 
      return true; 
     } 
     return false; 
    } 
} 

Ecco il business Object (MoveEntity) che sto cercando di mappare da

public class MoveEntity 
{ 
    public int SourceId { get; set; } 
    public int MoveId { get; set; } 
    public bool IsOrderDetailPageModified { get; set; } // TODO: Internal - Remove from data contract 
    public bool IsRoutingPageModified { get; set; } // TODO: Internal - Remove from data contract 
    public bool IsServicePageModified { get; set; } // TODO: Internal - Remove from data contract 
    public bool IsContentAndContainerPageModified { get; set; } // Rmove from data contract 
    public string FamilyRange { get; set; } // TODO: Is this being used? 
    public string Office { get; set; } 
    public string ActivityType { get; set; } 
    public string ActivitySubject { get; set; } 
    public string ActivityNote { get; set; } 
    public ContactEntity PrimaryOriginTransferee { get; set; } 
    public ContactEntity PrimaryDestinationTransferee { get; set; } 
    public CustomerEntity Customer { get; set; } 
    public AddressEntity OriginAddress { get; set; } 
    public AddressEntity DestinationAddress { get; set; } 
    public OrderEntity Order { get; set; } 
    public ShipmentEntity Shipment { get; set; } 
    public string CreatedBy { get; set; } 
    public DateTime CreatedDate { get; set; } 
    public string ModifiedBy { get; set; } 
    public DateTime ModifiedDate { get; set; } 
    public string SourceSystemId { get; set; } 
    public string SourceSystemName { get; set; } 
    public string Version { get; set; } 
    public string PortalId { get; set; } 

    public MoveEntity() 
    { 
     PrimaryOriginTransferee = new ContactEntity 
     { 
      ContactTypeId = ContactEntity.ContactType.PrimaryOriginationTransferee 
     }; 

     PrimaryDestinationTransferee = new ContactEntity 
     { 
      ContactTypeId = ContactEntity.ContactType.PrimaryDestinationTransferee 
     }; 

     OriginAddress = new AddressEntity 
     { 
      AddressTypeId = AddressEntity.AddressType.Origination 
     }; 

     DestinationAddress = new AddressEntity 
     { 
      AddressTypeId = AddressEntity.AddressType.Destination 
     }; 

     Order = new OrderEntity(); 
     Customer = new CustomerEntity(); 
     Shipment = new ShipmentEntity(); 
    } 

    public bool HasShipment() 
    { 
     if (Shipment.ShipmentId > 0) 
     { 
      return true; 
     } 
     return false; 
    } 
} 

Le proprietà all'interno di ciascuna classe corrispondono quasi perfettamente per nome, ma i tipi sono diversi. Pertanto ho tentato di eseguire una mappatura personalizzata usando l'espressione "MapFrom". Tuttavia, AutoMapper non sembra in grado di permettermi di puntare da un tipo di oggetto a un altro senza lamentarmi.

Ho anche provato a mappare property-to-property, senza fortuna. Sembrava qualcosa di simile:

.ForMember(dest => dest.PrimaryOriginTransferee.Email, opt => opt.MapFrom(src => src.PrimaryOriginTransferee.Email)) 

Tuttavia, quando si tenta questo, ricevo il seguente exeception:

deve risolvere al membro di alto livello. Nome parametro: lambdaExpression.

Ho trovato la documentazione disponibile per AutoMapper difficile da seguire. Qualcuno può indicarmi la giusta direzione su come utilizzare correttamente questa utility?

Grazie in anticipo per qualsiasi aiuto!

Adam

+0

Wall O Text ....: ~ ( –

+2

La prossima volta farò in modo che non ci siano informazioni sufficienti Grazie per il tuo contributo – letsgetsilly

+0

Lolz :) :) :) :) –

risposta

5

Alla fine ho finito per farlo funzionare da solo. Il codice che ho finito per usare è pubblicato qui sotto. La creazione della mappa degli oggetti nell'ordine corretto si è rivelata importante. Ho imparato molto a combattere attraverso questa cosa.

Ho organizzato le mie mappature in un profilo, che non entrerò qui, basti dire che se si può usare il mio esempio al di fuori di una classe ereditata dalla classe Profilo AutoMapper, si vorrà usare Mapper.CreateMap anziché solo Crea mappa.

private void CreateMaps() 
    { 

     CreateMap<ContactEntity, TransfereeEntityDto>(); 

     //ContactEntity Mapping 
     CreateMap<ContactEntity, TransfereeEntityDto>(); 

     //CustomerEntity Mapping 
     CreateMap<CustomerEntity, CustomerEntityDto>(); 

     //AddressEntity Mapping 
     CreateMap<AddressEntity, AddressEntityDto>(); 

     //ServiceEntity Mapping 
     CreateMap<ServiceEntity, ServiceEntityDto>() 
      .ForMember(dto => dto.ServiceTypeCode, opt => opt.MapFrom(source => source.TypeCode)) 
      .ForMember(dto => dto.ServiceDescriptionCode, opt => opt.MapFrom(source => source.DescriptionCode)) 
      .ForMember(dest => dest.SourceSystemName, opt => opt.ResolveUsing<SourceSystemNameResolver>().FromMember(entity => entity.SourceSystemName)); 


     //VehicleEntity Mapping 
     CreateMap<VehicleEntity, VehicleEntityDto>() 
      .ForMember(dest => dest.SourceSystemName, opt => opt.ResolveUsing<SourceSystemNameResolver>().FromMember(entity => entity.SourceSystemName)) 
      .ForMember(dto => dto.PortalId, option => option.Ignore()); //TODO: Should PortalID be mapped to anything? It is not in the entity. 

     //ContentEntity Mapping 
     CreateMap<ContentEntity, ContentEntityDto>() 
      .ForMember(dest => dest.SourceSystemName, opt => opt.ResolveUsing<SourceSystemNameResolver>().FromMember(entity => entity.SourceSystemName)); 

     //OrderForwardingEntity Mapping 
     CreateMap<OrderForwardingEntity, OrderForwardingEntityDto>(); 

     //ContainerEntity Mapping 
     CreateMap<ContainerEntity, ContainerEntityDto>() 
      .ForMember(dest => dest.SourceSystemName, opt => opt.ResolveUsing<SourceSystemNameResolver>().FromMember(entity => entity.SourceSystemName)); 

     //ShipmentForwardingEntity Mapping 
     CreateMap<ShipmentForwardingEntity, ShipmentForwardingEntityDto>(); 


     //ShipmentRouting Mapping 
     CreateMap<ShipmentRoutingEntity, ShipmentRoutingEntityDto>(); 

     //ShipmentEntity Mapping 
     CreateMap<ShipmentEntity, ShipmentEntityDto>() 
      .ForMember(dest => dest.SourceSystemName, opt => opt.ResolveUsing<SourceSystemNameResolver>().FromMember(entity => entity.SourceSystemName)) 
      .ForMember(dto => dto.Services, option => option.MapFrom(source => source.ServiceEntities)); 

     //Forwarder mapping 
     CreateMap<ContactEntity, ForwarderEntityDto>(); 
     //TODO: This property doesn't have any properties in the data contract 

     //OrderEntity Mapping 
     CreateMap<OrderEntity, OrderEntityDto>() 
      .ForMember(dest => dest.SourceSystemName, 
         opt => opt.ResolveUsing<SourceSystemNameResolver>().FromMember(entity => entity.SourceSystemName)); 
      //.ForMember(dto => dto.Forwarder, option => option.MapFrom(entity=>entity.Forwarder) 

     //MoveEntityMapping 
     CreateMap<MoveEntity, MoveEntityDto>() 
      .ForMember(dto => dto.SourceSystemName, opt => opt.ResolveUsing<SourceSystemNameResolver>().FromMember(entity => entity.SourceSystemName)); 

    } 
1

È necessario aggiungere le configurazioni di mappatura per i tipi di proprietà in cui il tipo di proprietà target è diverso da tipo di proprietà di destinazione.

Mapper.CreateMap<ContactEntity, TransfereeEntity>(); 
4

So che già ottenuto questo lavoro, ma ho intenzione di buttare questo là fuori nel caso in cui altre persone atterrano qui.

In AutoMapper, quando si hanno oggetti nidificati che devono essere mappati, anche se sono esattamente uguali (ad esempio una classe di contratto e una classe modello che corrispondono), è necessario definire le mappe per le classi figlio, quindi quando si definisce la mappa per il genitore, all'interno dell'opzione ".ForMember" è possibile utilizzare tali mappe secondarie per mappare il genitore. So che questo può sembrare confuso, ma un esempio lo renderà chiaro.

Diciamo che avete un il seguente:

namespace Contracts.Entities 
{ 
    public class Person 
    { 
     public string FirstName {get; set;} 

     public string LastName {get; set;} 

     public Address Address {get; set;}   
    } 

    public class Address 
    { 
     public string Street {get; set;} 

     public string City {get; set;} 

     public string State {get; set;}   
    } 
} 

namespace Model.Entities 
{ 
    public class Person 
    { 
     public string FirstName {get; set;} 

     public string LastName {get; set;} 

     public Address Address {get; set;}   
    } 

    public class Address 
    { 
     public string Street {get; set;} 

     public string City {get; set;} 

     public string State {get; set;}   
    } 
} 

Poi si va e definire le seguenti mappe:

Mapper.CreateMap<Contracts.Entities.Person, Model.Entities.Person>(); 
    Mapper.CreateMap<Contracts.Entities.Address, Model.Entities.Address>(); 

Si potrebbe pensare che automapper saprebbe utilizzare la mappa Indirizzo quando la mappatura di un contratto persona a una persona modello, ma non lo fa. Invece, ecco cosa devi fare:

 Mapper.CreateMap<Contracts.Entities.Person, Model.Entities.Person>() 
        .ForMember(dest => dest.Address, opt => opt.MapFrom(src => Mapper.Map<Contracts.Entities.Address, Model.Entities.Address>(src.Address))); 

Mapper.CreateMap<Contracts.Entities.Address, Model.Entities.Address>(); 

Quindi nel tuo caso si potrebbe definire una mappa Mapper.CreateMap<ContactEntity,TransfereeEntity>() quindi chiamare che mappa nello stesso modo in cui indirizzo di cui sopra al momento di definire la mappa per PrimaryOriginTransferee. OSSIA

Mapper.CreateMap<MoveEntity, MoveEntityDto>() 
.ForMember(dest => dest.PrimaryOriginTransferee , opt => opt.MapFrom(src => Mapper.Map<ContactEntity,TransfereeEntity>(src.PrimaryOriginTransferee))); 

Spero che questo aiuti qualcuno!

Problemi correlati