【问题标题】:Why AutoMapper is not Mapping mapping second level navigation property using ProjectTo?为什么 AutoMapper 不使用 ProjectTo 映射映射二级导航属性?
【发布时间】:2019-08-05 15:40:42
【问题描述】:

我有这个简单的课程

public class Store {
    public int Id { get; set; }

    //Other properties

    [JsonIgnore]
    public ICollection<Product> Products { get; set; }
}

还有我的 DTO

public class StoreDetails {
    public int Id { get; set; }

    //Other properties

    public ICollection<Product> Products { get; set; }
}

还有我的Product 班级:

public class Product {
    public int? Id { get; set; }

    //Other properties

    public ICollection<ProductAttribute> ProductAttributes { get; set; }
}

我的映射看起来像这样:

var storeDetails = await _context.Stores
    .Include(s => s.Products)
    .ThenInclude(p => p.ProductAttributes)
    .ProjectTo<StoreDetails>(new MapperConfiguration(c => c.CreateProfile("TEST", e => {
        e.CreateMap<Store, StoreDetails>();
    })))
    .SingleOrDefaultAsync(p => p.Id == id);

Store 对象中的一切看起来都很好,但在 StoreDetails 中,ProductAttributes 每次都是 null。

为什么 AutoMapper 不使用 ProjectTo 映射二级导航属性?

注意:我使用的是 AutoMapper 8.1.1。

【问题讨论】:

  • 您不需要包含在 ProjectTo 中。
  • 如果我没看错的话,Product 对两者来说是同一个类,所以不需要对其执行任何映射。您是否尝试在不使用 ThenInclude(p =&gt; p.ProductAttributes) 的情况下运行它?
  • @SSchulze 没有ThenInclude的结果相同
  • @LucianBargaoanu 有没有办法(我猜答案是否定的)强制对相等的源和目标(元素)类型进行投影?看起来 AssignableExpressionBinderEnumerableExpressionBinder 几乎不会强制投影源表达式。
  • 可能没有ToList,因为AssignableExpressionBinderEnumerableExpressionBinder 之前。更改顺序会完成您想要的,但是,正如我所说,没有它它对我有用。

标签: c# asp.net-core automapper


【解决方案1】:

我认为你应该像这样在你的类中添加虚拟属性

public class Store {
    public int Id { get; set; }

    //Other properties

    [JsonIgnore]
    public virtual ICollection<Product> Products { get; set; }
}

public class StoreDetails {
    public int Id { get; set; }

    //Other properties

    public virtual ICollection<Product> Products { get; set; }
}

也可以像这样使用 Profile 来映射

public class StoreProfile : Profile
{
    public StoreProfile ()
    {
        CreateMap<Store, StoreDetails>(MemberList.None).ReverseMap();
    }
}

然后在你的 startup.cs 中注册

services.AddAutoMapper();

这是您映射到配置文件的方式

private readonly IMapper _mapper;

var storeDetails = await _context.Stores
    .Include(s => s.Products)
    .ThenInclude(p => p.ProductAttributes)
    .Select(
      x => new ViewModel {
        SomeObject = _mapper.Map<Store, StoreDetails>(x)
      } 
    )
    .SingleOrDefaultAsync(p => p.Id == id);

下面是我使用的版本

<PackageReference Include="AutoMapper" Version="8.0.0" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="6.0.0" />

【讨论】:

  • 好的,我知道了。然后我应该在ProjectTo的参数中使用这个配置文件?
  • @Morasiu 只是更新我的答案。您可以使用_mapper.Map。请根据您的代码进行相应调整
  • 哦...现在我明白了。所以我不应该使用ProjectTo
  • 我没有使用 ProjectTo,所以我可以给你我的意见。但这就是我映射关系数据的方式
  • 您是否将您的个人资料添加到services.AddAutoMapper() 作为参数?或者它正在做一些自动反射并自己添加所有配置文件?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-01
  • 1970-01-01
  • 2014-06-30
  • 2020-01-25
相关资源
最近更新 更多