将多个源合并到一个目标中

时间:2017-04-25 15:03:56

标签: c# asp.net-mvc entity-framework automapper entity-framework-core

我想使用AutoMapper将2个域对象组合成单个数据传输对象。

域名模型:

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; }
}

映射:

 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();

当我尝试上面的映射时:

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

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

我收到以下错误:

  

缺少类型映射配置或不支持的映射。

     

映射类型: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]] - &gt; Fwims.Core.ViewModel.Setting.PreferenceVM

看起来我的映射是错误的,我尝试过的任何工作都没有。如何将Domain对象正确映射到数据传输对象?

1 个答案:

答案 0 :(得分:3)

下面

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();

您从ICollection<TSource>创建映射。

但是稍后你试图映射IQeryable<TSource>。虽然AutoMapper可以使用基本映射来映射派生类,但IQueryable<T>不是从ICollection<T>派生的,因此缺少类型映射异常。

解决方案是从IQueryable<T>ICollection<T>的某个公共基接口创建映射,IEnumerable<T>

所以用以下内容替换上面的内容:

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));

目前的问题将得到解决。

请注意ReverseMap在这种情况下不起作用,所以我只是删除了它。如果您需要此类功能,则必须手动创建该映射(最终使用ConvertUsing,因为没有目标成员)。