【发布时间】: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中吗? -
可能不是——我基本上只是在复制我在模型类中的内容。但是,删除它并没有什么不同。
标签: c# asp.net-core entity-framework-core odata automapper