[英]Web API 2: OData 4: Single Controller with Common Repository does not work with IQueryable when passed to the OK method
[英]OData IQueryable DTO mapping in separate method does not work
我對 DTO 映射有疑問。 我正在使用 OData WebAPI,由於分頁、排序、過濾,我需要使用 IQueryable...當我在我的 WebAPI 控制器中使用此代碼(為此目的而簡化)時,它可以工作
return Ok(_dataService.GetEntities(idUser).Select(e => new EntityDTO
{
ID = e.ID,
Name = e.Name
}));
但是當我有單獨的 DTO 映射方法時它不起作用。
return Ok(_dataService.GetEntities(idUser).Select(e => _dataService.MapToEntityDTO(e)));
我的 _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
};
}
你能請人解釋一下這有什么問題嗎? 感謝幫助。
GetEntities 似乎正在返回一個IQueryable
,EF 將推遲執行,直到需要具體化結果。 如果您嘗試調用一些任意 C# 方法 (MapToEntity),這將失敗,因為 EF 無法將其轉換為 SQL。
您應該考慮使用的是 Automapper,它包含一個名為ProjectTo
的方法,該方法可以與 EF 的IQueryable
集成,以通過配置的映射器投影您的 DTO。
var dtos = _dataService.GetEntities(idUser)
.ProjectTo<EntityDTO>(config)
.ToList();
return Ok(dtos);
其中“config”是 Automapper 配置類的一個實例,其中包含將實體轉換為 DTO 的映射配置。
使用不與IQueryable
集成的自定義映射器的替代方法是,您必須先實現實體,然后在內存中執行映射:
var dtos = _dataService.GetEntities(idUser)
.ToList() // Materializes the entities
.Select(e => _dataService.MapToEntityDTO(e))
.ToList();
return Ok(dtos);
這種方法的缺點是它需要更多的內存和時間從服務器首先將實體加載到內存中,然后執行映射Select
。 這還要求 GetEntities() 方法確保可能被映射的任何/所有相關實體都是預先加載的,否則它們將觸發延遲加載或保留為 #null。 這可能會耗盡時間和內存使用,而實際上可能需要很少的相關數據。
使用ProjectTo
投影,查詢將自動獲取所需的任何相關詳細信息,而無需急切加載關系或觸發延遲加載。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.