.NET Core 6 OData查询报错:LINQ表达式无法翻译求解决方案
问题解决:LINQ表达式无法转换,OData过滤无法直接作用于映射后的IQueryable
核心原因
OData的EnableQuery特性会将URL查询参数(如$orderby=Id)转换为针对IQueryable<BankViewModel>的LINQ表达式,但AutoMapper的ProjectTo生成的查询结构,会让EF Core无法解析new BankViewModel{}.Id这类针对ViewModel的表达式(EF无法识别该属性对应实体的哪个字段)。调用ToList()时是先加载全量数据到内存再执行查询,所以能运行但效率低下。
解决方案
1. 修正OData模型配置
确保OData模型明确绑定BankViewModel,避免自动识别错误:
var modelBuilder = new ODataConventionModelBuilder(); // 明确指定EntitySet的ViewModel类型,替代无类型的EntitySet modelBuilder.EntitySet<BankViewModel>("BankOdata"); builder.Services.AddControllers().AddOData( options => { options.EnableQueryFeatures(1000); options.AddRouteComponents("odata", modelBuilder.GetEdmModel()); } );
2. 调整查询流程:先执行OData查询,再映射ViewModel
让OData的过滤、排序等操作先作用于实体Bank的IQueryable,再通过AutoMapper映射为BankViewModel,确保所有查询逻辑在数据库层面执行。
修改服务层接口
新增返回实体IQueryable的方法:
public interface IBankService : IDisposable { IQueryable<BankViewModel> GetAll(); // 新增方法,返回实体的IQueryable IQueryable<Bank> GetAllEntities(); }
实现服务层方法
public class BankService : IBankService { // ... 原有构造函数及依赖 public IQueryable<Bank> GetAllEntities() { return _bankRepository.GetAll(); } // ... 原有方法 }
修改控制器逻辑
public class BankOdataController : ODataController { private readonly IBankService _bankService; private readonly IMapper _mapper; public BankOdataController(IBankService bankService, IMapper mapper) { _bankService = bankService; _mapper = mapper; } [EnableQuery] public IQueryable<BankViewModel> Get() { // 先获取实体IQueryable,让OData执行数据库层面的查询 var bankEntities = _bankService.GetAllEntities(); // 最后映射为ViewModel return bankEntities.ProjectTo<BankViewModel>(_mapper.ConfigurationProvider); } }
3. 可选:显式配置OData模型属性
如果ViewModel属性识别仍有问题,可手动声明OData模型的属性和主键:
var bankEntityType = modelBuilder.EntitySet<BankViewModel>("BankOdata").EntityType; // 声明主键 bankEntityType.HasKey(b => b.Id); // 显式暴露需要查询的属性 bankEntityType.Property(b => b.Name); // 其他需要的属性...
内容的提问来源于stack exchange,提问作者Navid Salajegheh
相关产品推荐
相关产品推荐

