简体   繁体   中英

Automapper many to many mapping in 3-Tier architecture

I have two Entities model on DataAccessLayer:

Consumer

 public class Consumer 
 {
    public int Id { get; set; }
    public string Name { get; set; }
    public string PhoneNumber { get; set; }

    public virtual ICollection<Contractor> Contractors { get; set; }

    public Consumer()
    {
        Contractors = new List<Contractor>();
    }
 }

Contractor

public class Contractor 
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string PhoneNumber { get; set; }
    public string Email { get; set; }

    public virtual ICollection<Consumer> Consumers { get; set; }

    public Contractor()
    {
        Consumers = new List<Consumer>();
    }
}

...and two class on Transfer Data Layer:


ConsumerTransfer

 public class ConsumerTransfer
 {
    public int Id { get; set; }
    public string Name { get; set; }
    public string PhoneNumber { get; set; }
    public IList<ContractorTransfer> ContractorTransfer { get; set; } 
 }

ContractorTransfer

 public class ContractorTransfer
 {
    public int Id { get; set; }
    public string Name { get; set; }
    public string PhoneNumber { get; set; }
    public string Email { get; set; }
 }

**

How can I get data from Consumer to ConsumerTransfer?

**

I tried to do it this way

 public IEnumerable<ConsumerTransfer> GetСonsumers()
    {
        Mapper.Initialize(cfg => cfg.CreateMap<Consumer, ConsumerTransfer>()
            .ForMember(dto=>dto.Id, opt => opt.MapFrom(src => src.Id))
            .ForMember(dto => dto.Name, opt => opt.MapFrom(src => src.Name))
            .ForMember(dto => dto.PhoneNumber, opt => opt.MapFrom(src => src.PhoneNumber))
            .ForMember(dto => dto.ContractorTransfer, opt => opt.MapFrom(src => src.Contractors))
            );
        return Mapper.Map<IEnumerable<Consumer>, IEnumerable<ConsumerTransfer>>(Database.Consumers.GetAll()); 
    }

First of all, I'd rename your "ContractorTransfer" property to "Contractors". Generally I keep property names the same between DTOs and source types. Not a 100% rule, but unless I have a REALLY good reason on the client side (serialization concerns, whatever), then I don't change property names.

Second, your AutoMapper config is in the wrong place. You need to put the Initialize in the startup of your application, not right next to your mapping.

Third, your configuration is way too verbose. AutoMapper automatically maps properties with the same name.

Fourth, you're missing a map for the second set of source/destination types. Assuming you've fixed your inconsistent property name, here's your config:

Mapper.Initialize(cfg => {
    cfg.CreateMap<Consumer, ConsumerTransfer>();
    cfg.CreateMap<Contract, ContractTransfer>();
});

Then later on when you execute the map:

Mapper.Map<Consumer, ConsumerTransfer>(consumer);

That's it.

public IEnumerable<ConsumerTransfer> GetСonsumers()
{
    Mapper.Initialize(cfg =>
    {
        cfg.CreateMap<Consumer, ConsumerTransfer>()
            .ForMember(dto => dto.Id, opt => opt.MapFrom(src => src.Id))
            .ForMember(dto => dto.Name, opt => opt.MapFrom(src => src.Name))
            .ForMember(dto => dto.PhoneNumber, opt => opt.MapFrom(src => src.PhoneNumber))
            .ForMember(dto => dto.ContractorTransfer, opt => opt.MapFrom(src => src.Contractors));

        cfg.CreateMap<Contractor, ContractorTransfer>();
    });

    return Mapper.Map<IEnumerable<ConsumerTransfer>>(Database.Consumers.GetAll());
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM