linq 单独方法中的OData IQueryable DTOMap不起作用

mjqavswn  于 2022-12-06  发布在  其他
关注(0)|答案(1)|浏览(135)

I have issues with DTO mapping. I'm using OData WebAPI and I need to use IQueryable due to paging, sorting, filtering... When I use this code (simplified for this purpose) in my WebAPI controller, it works

return Ok(_dataService.GetEntities(idUser).Select(e => new EntityDTO 
{
    ID = e.ID,
    Name = e.Name   
}));

but when I have separate method for DTO mapping it does not work.

return Ok(_dataService.GetEntities(idUser).Select(e => _dataService.MapToEntityDTO(e)));

Methods in my _dataService object (simplified)

public IQueryable<Entity> GetEntities(long idUser)
{        
    return from z in _context.Entities select z;
}

public EntityDTO MapToEntityDTO(Entity entity) {
    return new EntityDTO {
            ID = entity.ID,
            Name = entity.Name  
        };
}

Could you please someone explain me what is wrong with that ? Thanks for help.

xqkwcwgp

xqkwcwgp1#

看起来GetEntities正在返回一个IQueryable,EF将延迟执行,直到需要实现结果。如果您尝试调用某个任意的C#方法(MapToEntity),这将失败,因为EF无法将其向下转换为SQL。
您应该考虑使用Automapper,它包含一个名为ProjectTo的方法,该方法可以与EF的IQueryable集成,以便通过配置的Map器投影您的DTO。

var dtos = _dataService.GetEntities(idUser)
    .ProjectTo<EntityDTO>(config)
    .ToList();
return Ok(dtos);

其中“config”是自动Map器配置类的示例,包含将实体转换为DTO的Map配置。
使用不与IQueryable集成的自定义Map器的另一种方法是,您必须首先实体化实体,然后在内存中执行Map:

var dtos = _dataService.GetEntities(idUser)
    .ToList() // Materializes the entities
    .Select(e => _dataService.MapToEntityDTO(e))
    .ToList();
return Ok(dtos);

这种方法的缺点是,首先将实体加载到内存中,然后执行MapSelect,需要服务器提供更多的内存和时间。()方法确保可能被Map的任何/所有相关实体都被立即加载,否则它们将触发延迟加载或被保留为#null。这可能会在实际上几乎不需要这些相关数据的情况下消耗大量时间和内存。
使用ProjectTo投影,查询将自动获取所需的任何相关详细信息,而无需立即加载关系或触发延迟加载的开销。

相关问题