Merge multiple sources into a single destination

asp.net-mvc automapper c# entity-framework entity-framework-core

Question

I want to combine 2 Domain Objects into a single data transfer object using AutoMapper.

Domain Model:

public class Service  {
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public ICollection<DownloadService> DownloadServices { get; set; } = new HashSet<DownloadService>();
}

public class DownloadService {
    public int Id { get; set; }
    public int PageLimit { get; set; }
    public virtual int ServiceId { get; set; }
    public virtual Service Service { get; set; }
}

public class Volume {
    public override int Id { get; set; }
    public bool IsActive { get; set; }
    public string Path { get; set; }
    public string Description { get; set; }
}

DTO:

 public class PreferenceVM {
        public ICollection<VolumeVM> Volumes { get; set; }
        public ICollection<ServiceVM> Services { get; set; }
 }

 public class ServiceVM {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public ICollection<DownloadServiceVM> DownloadServices { get; set; } = new HashSet<DownloadServiceVM>();
 }

public class DownloadServiceVM {
        public int Id { get; set; }
        public int PageLimit { get; set; }
        public int CleaningInterval { get; set; }
}

 public class VolumeVM {
        public int Id { get; set; }
        public bool IsActive { get; set; }
        public string Path { get; set; }
        public string Description { get; set; }
}

Mapping:

 cfg.CreateMap<Volume, VolumeVM>().ReverseMap();
 cfg.CreateMap<DownloadService, DownloadServiceVM>().ReverseMap();
 cfg.CreateMap<Service, ServiceVM>()
     .ForMember(d => d.DownloadServices, opt => opt.MapFrom(s => s.DownloadServices))
     .ReverseMap();

 cfg.CreateMap<ICollection<Volume>, PreferenceVM>()
            .ForMember(x => x.Volumes, y => y.MapFrom(src => src)).ReverseMap();
 cfg.CreateMap<ICollection<Service>, PreferenceVM>()
            .ForMember(x => x.Services, y => y.MapFrom(src => src)).ReverseMap();

when I try the mapping above:

 var services = serviceRepository.GetAll();
 var volumes = volumeRepository.GetAll();

 var entities = mapper.Map<PreferenceVM>(services);
 entities = mapper.Map(volumes, entities);

I get the following errors:

Missing type map configuration or unsupported mapping.

Mapping types: EntityQueryable1 -> PreferenceVM Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable1[[Fwims.Core.Data.Model.Setting.Service, Fwims.Core.Data.Model, Version=1.0.1.10, Culture=neutral, PublicKeyToken=null]] -> Fwims.Core.ViewModel.Setting.PreferenceVM

It looks like my mapping is wrong, nothing I have tried has worked. How do I properly map the Domain objects to the Data transfer objects?

1
3
4/25/2017 4:51:03 PM

Accepted Answer

Here

cfg.CreateMap<ICollection<Volume>, PreferenceVM>()
    .ForMember(x => x.Volumes, y => y.MapFrom(src => src)).ReverseMap();

and

cfg.CreateMap<ICollection<Service>, PreferenceVM>()
    .ForMember(x => x.Services, y => y.MapFrom(src => src)).ReverseMap();

you create mappings from ICollection<TSource>.

However later on you are trying to map IQeryable<TSource>. While AutoMapper can use a base mapping to map a derived class, IQueryable<T> does not derive from ICollection<T>, hence the missing type map exception.

The solution is to create a mapping from some common base interface of IQueryable<T> and ICollection<T>, which is IEnumerable<T>.

So replace the above with:

cfg.CreateMap<IEnumerable<Volume>, PreferenceVM>()
    .ForMember(x => x.Volumes, y => y.MapFrom(src => src));
cfg.CreateMap<IEnumerable<Service>, PreferenceVM>()
    .ForMember(x => x.Services, y => y.MapFrom(src => src));

and the current issue will be solved.

Note that ReverseMap does not work in such scenarios, so I've just removed it. If you need such functionality, you have to create that mappings manually (eventually using ConvertUsing because there is no destination member).

3
4/25/2017 5:25:48 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow