简体   繁体   English

单独方法中的 OData IQueryable DTO 映射不起作用

[英]OData IQueryable DTO mapping in separate method does not work

I have issues with DTO mapping.我对 DTO 映射有疑问。 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我正在使用 OData WebAPI,由于分页、排序、过滤,我需要使用 IQueryable...当我在我的 WebAPI 控制器中使用此代码(为此目的而简化)时,它可以工作

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.但是当我有单独的 DTO 映射方法时它不起作用。

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

Methods in my _dataService object (simplified)我的 _dataService 对象中的方法(简化)

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.感谢帮助。

It would appear that GetEntities is returning an IQueryable that EF would be deferring execution until the results need to be materialized. GetEntities 似乎正在返回一个IQueryable ,EF 将推迟执行,直到需要具体化结果。 This would fail if you try calling some arbitrary C# method (MapToEntity) because EF cannot translate that down into SQL.如果您尝试调用一些任意 C# 方法 (MapToEntity),这将失败,因为 EF 无法将其转换为 SQL。

What you should consider using is Automapper which contains a method called ProjectTo which can integrate with EF's IQueryable to project your DTOs through a configured mapper.您应该考虑使用的是 Automapper,它包含一个名为ProjectTo的方法,该方法可以与 EF 的IQueryable集成,以通过配置的映射器投影您的 DTO。

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

Where "config" is an instance of the Automapper Configuration class containing the mapping config to convert the Entity(ies) to DTO(s).其中“config”是 Automapper 配置类的一个实例,其中包含将实体转换为 DTO 的映射配置。

The alternative with a custom mapper that doesn't integrate with IQueryable is that you would have to materialize the entities first, then perform the mapping in memory:使用不与IQueryable集成的自定义映射器的替代方法是,您必须先实现实体,然后在内存中执行映射:

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

The disadvantages of this approach are that it requires more memory and time from the server to load the entities into memory first, then perform the mapping Select .这种方法的缺点是它需要更多的内存和时间从服务器首先将实体加载到内存中,然后执行映射Select This also requires that the GetEntities() method ensures that any/all related entities that might be mapped are eager loaded, otherwise they would either trigger lazy loads or be left #null.这还要求 GetEntities() 方法确保可能被映射的任何/所有相关实体都是预先加载的,否则它们将触发延迟加载或保留为 #null。 This can blow out time and memory usage where little of this related data might actually be needed.这可能会耗尽时间和内存使用,而实际上可能需要很少的相关数据。

With the ProjectTo projection, the queries will automatically fetch whatever related details are needed without the overhead of needing to eager load relations or tripping lazy loads.使用ProjectTo投影,查询将自动获取所需的任何相关详细信息,而无需急切加载关系或触发延迟加载。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM