Voglio combinare 2 oggetti di dominio in un singolo oggetto di trasferimento dati utilizzando AutoMapper.
Modello di dominio:
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; }
}
Mappatura:
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();
quando provo la mappatura sopra:
var services = serviceRepository.GetAll();
var volumes = volumeRepository.GetAll();
var entities = mapper.Map<PreferenceVM>(services);
entities = mapper.Map(volumes, entities);
Ottengo i seguenti errori:
Configurazione della mappa del tipo mancante o mapping non supportato.
Tipi di mapping: EntityQueryable
1 -> PreferenceVM Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable
1 [[Fwims.Core.Data.Model.Setting.Service, Fwims.Core.Data.Model, Version = 1.0.1.10, Culture = neutral, PublicKeyToken = null]] -> Fwims.Core.ViewModel.Setting.PreferenceVM
Sembra che la mia mappatura sia sbagliata, nulla di ciò che ho provato ha funzionato. Come mappare correttamente gli oggetti Dominio agli oggetti Trasferimento dati?
Qui
cfg.CreateMap<ICollection<Volume>, PreferenceVM>()
.ForMember(x => x.Volumes, y => y.MapFrom(src => src)).ReverseMap();
e
cfg.CreateMap<ICollection<Service>, PreferenceVM>()
.ForMember(x => x.Services, y => y.MapFrom(src => src)).ReverseMap();
si creano mappature da ICollection<TSource>
.
Tuttavia, in seguito si sta tentando di mappare IQeryable<TSource>
. Mentre AutoMapper può utilizzare una mappatura di base per mappare una classe derivata, IQueryable<T>
non deriva da ICollection<T>
, quindi l'eccezione di mappa del tipo mancante.
La soluzione è creare un mapping da un'interfaccia di base comune di IQueryable<T>
e ICollection<T>
, che è IEnumerable<T>
.
Quindi sostituire quanto sopra con:
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));
e il problema attuale sarà risolto.
Nota che ReverseMap
non funziona in questi scenari, quindi l'ho appena rimosso. Se hai bisogno di tale funzionalità, devi creare tali mappature manualmente (eventualmente utilizzando ConvertUsing
perché non esiste un membro di destinazione).