我正在寻求以.NET核心实现OData API。
我的基础数据提供者有一个方法:
Task<ICollection<TDto>> GetList(Expression<Func<TDto, bool>> filter, int skip = 0, int take = int.MaxValue);
我需要将Odata FilterQueryOption转换为
Expression<Func<TDto, bool>>
我发现了这个:How to Transform an OData Filter to an Expression
这使我更接近-但我仍然需要从Expression转换为
Expression<Func<TDto, bool>>
我找到了这个Convert Expression To Expression<Func<T,bool>
将这两种技术放在一起,我最终得到:
private async Task<IActionResult> ProcessFilter(ODataQueryOptions<BookDto> oDataQueryOptions)
{
var expression = oDataQueryOptions.Filter.ToExpression<BookDto>();
var dtoExpression = expression.Convert<BookDto>();
var skip = oDataQueryOptions.Skip?.Value == 0 ? 0 : Convert.ToInt32(oDataQueryOptions.Skip?.Value);
var take = oDataQueryOptions.Top?.Value == 0 ? int.MaxValue : Convert.ToInt32(oDataQueryOptions.Top?.Value);
var result = await _bookService.GetList(dtoExpression, skip, take);
return Ok(result);
}
我的“ ToExpression()”方法是第一个SO链接:
public static Expression ToExpression<TElement>(this FilterQueryOption filter)
{
IQueryable queryable = Enumerable.Empty<TElement>().AsQueryable();
queryable = filter.ApplyTo(queryable, new ODataQuerySettings());
return queryable.Expression;
}
和Expression上的“转换”扩展方法是:
public static Expression<Func<T, bool>> Convert<T>(this Expression expression)
{
var item = Expression.Parameter(typeof(T), "item");
var body = expression.GetPredicateExpression(item);
return Expression.Lambda<Func<T, bool>>(body, item);
}
运行此命令-我得到一个例外: ArgumentException:类型'System.Linq.IQueryable`1 [ExampleApi.Dto.BookDto]'的表达式不能用于返回类型'System.Boolean'
它在这里的Convert扩展中被抛出:
return Expression.Lambda<Func<T, bool>>(body, item);
我发现了这篇(有点过时的)文章:Converting ODataQueryOptions to Expression,这是我正在尝试做的事情的“一类”。作者首先从TDTO到TEntity的MethodCallExpression替换了MemberExpression-然后他使用DbContext将所得的Expression转换为
Expression<Func<TEntity,bool>>
我想从$ filter表达式转换为Expression<Func<TDto, bool>
,并将其用作业务逻辑/数据访问的参数
_bookService.GetList(dtoExpression,skip, take);
原因是我从
进行了转换Expression<Func<TDto,bool>>
到
Expression<Func<TEntity,bool>>
在我的数据访问/服务类中(这些类不仅在Web应用程序中使用)。