【问题标题】:Cannot map inner navigation property using automapper. EF Core无法使用自动映射器映射内部导航属性。 EF 核心
【发布时间】:2021-06-24 09:14:50
【问题描述】:

我有针对该特定问题的此类实体:AlbumPhoto。每个Album 都包含一个Photos 的集合

和 Dto 类:AlbumWithPhotosDto,其中包含PhotoDto集合

在我的自动映射器配置文件中,我描述了所有实体的映射规则:

CreateMap<Photo, PhotoDto>()
                .ForMember(dest => dest.AverageRate, opt => opt.MapFrom(src => src.Ratings.Average(r => r.Rate)))
                .ForMember(dest => dest.RatesCount, opt => opt.MapFrom(src => src.Ratings.Count))
                .ReverseMap();

 CreateMap<Album, AlbumWithPhotosDto>()
                .ForMember(dest => dest.PhotosNum, opt => opt.MapFrom(src => src.Photos.Count))
                .ReverseMap();

首先我使用LazyLoadingProxies,当我尝试将Album映射到AlbumWithPhotosDto时。

我遇到了异常:

错误映射类型。

映射类型:相册 -> AlbumWithPhotosDto DAL.Entities.Album -> BLL.DataTransferObjects.AlbumWithPhotosDto

类型映射配置:相册 -> AlbumWithPhotosDto DAL.Entities.Album -> BLL.DataTransferObjects.AlbumWithPhotosDto

目标成员:照片

然后我在显式加载时更改了延迟加载,例如:

_context.Albums
            .Include(a => a.Photos)
            .Include(a => a.Author)

但我又遇到了同样的例外。我该如何解决这个问题?

这里是类的附加定义:

 public class Album : IEntity<int>
    {
        public int Id { get; set; }
        /// <summary>
        /// Album name.
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// Album short description.
        /// </summary>
        public string Description { get; set; }
        /// <summary>
        /// Whether the other users can view and rate the album photos or not.
        /// </summary>
        public bool IsPrivate { get; set; }
        /// <summary>
        /// Foreign key, creator's id.
        /// </summary>
        public string AuthorId { get; set; }
        /// <summary>
        /// User who created the album but not obviously author of all photos.
        /// </summary>
        public virtual User Author { get; set; }
        /// <summary>
        /// Photos in album.
        /// </summary>
        public virtual ICollection<Photo> Photos { get; set; } = new HashSet<Photo>();
    }
public class Photo : IEntity<int>
    {
        public int Id { get; set; }
        /// <summary>
        /// Optional photo short description.
        /// </summary>
        public string Description { get; set; }
        /// <summary>
        /// Path to the photo file on the hard drive.
        /// </summary>
        public string FileName { get; set; }
        /// <summary>
        /// Date and time of uploading.
        /// </summary>
        public DateTime UploadDate { get; set; }
        /// <summary>
        /// Photo ratings by users.
        /// </summary>
        public virtual ICollection<Rating> Ratings { get; set; } = new HashSet<Rating>();
        /// <summary>
        /// Foreigh key, author's id.
        /// </summary> 
        public string AuthorId { get; set; }
        public virtual User Author { get; set; }
        public int AlbumId { get; set; }
        public virtual Album Album { get; set; }
    }
public class AlbumWithPhotosDto : IDtoMetadata
    {
        public int Id { get; set; }
        public string Description { get; set; }
        public string AuthorId { get; set; }
        public int PhotosNum { get; set; }
        public ICollection<PhotoDto> Photos { get; set; }
    }
public class PhotoDto : IDtoMetadata
    {
        public int Id { get; set; }
        public string Base64 { get; set; }
        public string Description { get; set; }
        public double AverageRate { get; set; }
        public int RatesCount { get; set; }
        public DateTime UploadDate { get; set; }
        public string AuthorId { get; set; }
        public ICollection<RatingDto> Ratings { get; set; }
    }

【问题讨论】:

  • Rating 的映射也存在,为了简洁,我跳过了这个
  • 可能上下文已被处理。在映射之前,您是否尝试在查询末尾添加 .ToArray()?
  • 是的,我强制执行查询,成功查询了相册对象,上下文正常

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


【解决方案1】:

您的查询中没有包含Ratings。因此,AutoMapper 基本上是试图在一个空集合上调用.Average(),因此失败了。

将您的查询修改为 -

var albums = _context.Albums
            .Include(a => a.Photos).ThenInclude(p => p.Ratings)
            .Include(a => a.Author)
            .ToList();

【讨论】:

  • 我做了,没什么变化,我把dto类里的ratings集合注释掉了,都是一样的。
  • @AlexandrBarylo 那么请编辑帖子并分享完整的映射代码、所有模型,以及您如何调用.Map() 方法。
【解决方案2】:

正如异常消息中所述,问题在于“AlbumWithPhotosDto”中的“照片”属性。将类型更改为“列表”,然后尝试这种方式。

【讨论】:

    【解决方案3】:

    经过一步一步的投资,我意识到问题出在映射配置中的那一行:

    CreateMap<Photo, PhotoDto>()
                    .ForMember(dest => dest.AverageRate, opt => opt.MapFrom(src => src.Ratings.Average(r => r.Rate)))
    

    解决方案是在评分为 0 时注意默认值。

    CreateMap<Photo, PhotoDto>()
                    .ForMember(dest => dest.AverageRate, opt => opt.MapFrom(src => src.Ratings.Select(r => r.Rate).DefaultIfEmpty(0).Average()))
    

    现在连我之前认为与自动映射器不兼容的 LazyLoadingProxies 都已成功映射。

    【讨论】:

      猜你喜欢
      • 2020-01-01
      • 2012-03-27
      • 2021-09-15
      • 1970-01-01
      • 2023-02-10
      • 2017-09-17
      • 1970-01-01
      • 2021-03-31
      • 1970-01-01
      相关资源
      最近更新 更多