无法使用 OData、EF Core 和 AutoMapper 映射 List<> 导航属性
Posted
技术标签:
【中文标题】无法使用 OData、EF Core 和 AutoMapper 映射 List<> 导航属性【英文标题】:Unable to map List<> navigational properties using OData, EF Core and AutoMapper 【发布时间】:2020-01-01 15:10:51 【问题描述】:我目前正在编写一个 ASP .NET Core API,利用 OData 进行查询,并使用 Entity Framework 与数据库对话。
我想将域对象与发送给用户的 DTO 分开,因此也开始使用 AutoMapper 将实体框架查询结果转换为我创建的 DTO。
此时(在我测试时),我的 DTO 和域对象是相同的 - 只是公共 getter/setter 属性。 DTO 示例如下:
public class NoteDTO
public int Id get; set;
public string Body get; set;
public string Conclusion get; set;
public string Title get; set;
public ManagerDTO Manager get; set;
public class ManagerDTO
public int Id get; set;
public virtual List<ProductDto> Products get; set;
public class ProductDto
public int Id get; set;
我的 NotesController 中还有一个用于获取笔记的测试方法(同样,使用 OData),如下所示:
[HttpGet]
[EnableQuery]
public IQueryable<NoteDTO> GetMeeting()
var config = new MapperConfiguration(cfg =>
cfg.CreateMap<Note, NoteDTO>();
cfg.CreateMap<Product, ProductDto>();
cfg.CreateMap<Manager, ManagerDTO>()
.ForMember(md => md.Products, conf => conf.MapFrom(m => m.Products));
);
return _context.Notes.ProjectTo<NoteDTO>(config);
然后我尝试使用以下查询访问我的 API:
https://localhost:5001/api/Notes?$select=Id,Body,Conclusion&$top=5&$expand=Manager($select=Id)
但是,这失败了,在堆栈跟踪中,我收到以下错误消息:
System.ArgumentException: Expression of type 'System.Collections.Generic.IEnumerable`1[System.Tuple`3[TestEntityFramework.DataObjects.ProductDto,Microsoft.EntityFrameworkCore.Query.Internal.MaterializedAnonymousObject,Microsoft.EntityFrameworkCore.Query.Internal.MaterializedAnonymousObject]]' cannot be used for parameter of type 'System.Collections.Generic.IEnumerable`1[TestEntityFramework.DataObjects.ProductDto]' of method 'System.Collections.Generic.IEnumerable`1[TestEntityFramework.DataObjects.ProductDto] _ToEnumerable[ProductDto](System.Collections.Generic.IEnumerable`1[TestEntityFramework.DataObjects.ProductDto])'
如果我从 ManagerDTO 对象和相关的产品映射配置中删除列表,则上述查询成功。
我在 GitHub 问题上看到了这条评论,听起来像是同样的问题,但尝试实施该建议并没有帮助(假设我理解正确):https://github.com/AutoMapper/AutoMapper/issues/2853#issuecomment-482317381
还有其他人遇到过这个问题吗?我仍然习惯 AutoMapper,所以可能错过了一些明显的东西,但是通过搜索这似乎是一个相当罕见的问题,因此很难找到关于这里发生了什么的指针。
对于将 OData 查询转换为实体框架,然后再转换回 DTO 的最佳方式,我愿意接受任何其他建议 - 如果我在这里所做的不是最佳的!
【问题讨论】:
virtual
需要在ManagerDTO.Products
中吗?
可能不是——我基本上只是在复制我在模型类中的内容。但是,删除它并没有什么不同。
【参考方案1】:
您是否在使用 Automapper 集合扩展?如果没有,这应该可以解决您的问题:https://github.com/AutoMapper/AutoMapper.Collection
【讨论】:
感谢您的回复!今天我正在查看 AutoMapper ExpressionMapping 库,因为这听起来更像是我正在寻找的东西。使用它我可以生成我最初想要的查询,但是由于每次调用都会完成数据库查询,而不是通常的缓存 EF 似乎做的,所以性能不足。 这不起作用,除非您映射列表本身。如果列表是类的导航属性,则 Automapper.Collection 无效。我确信这应该有效,但它没有。 你的映射看起来像这样吗?:this.CreateMap以上是关于无法使用 OData、EF Core 和 AutoMapper 映射 List<> 导航属性的主要内容,如果未能解决你的问题,请参考以下文章
带有 EF 和自动映射器的 OData:无法比较..'。仅支持原始类型、枚举类型和实体类型
使用 EF 和 WebAPI,如何返回 ViewModel 并支持 IQueryable/OData? [复制]
使用 Asp.Net WebApi + EF + Odata 深度插入数据