在没有EF / Nhibernate的情况下解析ODataQueryOptions <type>

时间:2016-03-13 17:35:45

标签: c# asp.net-web-api odata

我有一个包含大型代码库的项目,该代码库使用内部数据访问层来处理数据库。但是,我们希望支持OData访问系统。我对C#中的表达式树很满意。我如何得到我可以在这里解析的东西,以获得他们实际查询的结构?

有没有办法从这个东西中获取AST,我可以变成sql代码?

2 个答案:

答案 0 :(得分:0)

基本上,您需要实现自己的Query Provider,它知道如何将表达式树转换为基础查询。

控制器方法的简化版本是:

    [ODataRoute("foo")]
    public List<Foo> GetFoo(ODataQueryOptions<Foo> queryOptions)
    {
        var queryAllFoo = _myQueryProvider.QueryAll<Foo>();
        var modifiedQuery = queryOptions.ApplyTo(queryAllFoo);
        return modifiedQuery.ToList();
    }

然而!

  1. 这不是一件容易的事,我花了大约一个月的时间来实现自定义OData查询处理
  2. 您需要构建EDM模型,因此WebApi OData可以处理和构建正确的表达式树
  3. 它可能涉及反射,在运行时在动态程序集中创建类型(用于投影),编译lambda表达式以获得最佳性能
  4. WebAPI OData组件有一些限制,所以如果你想让关系工作,你需要花费更多的额外时间,所以在我们的例子中我们做了一些自定义查询字符串转换(处理前)并将连接注入到表达式树中需要
  5. 在一个答案中有太多细节无法解释,这有很长的路要走..
  6. 祝你好运!

答案 1 :(得分:0)

您可以使用ODataQueryOptions<T>获取$filter$orderby查询选项的抽象语法树。 ($skip$top也可用作已解析的整数。)由于您不需要/想要LINQ支持,您可以简单地将AST传递给存储库方法,然后访问存储库方法ASTs构建适当的SQL存储过程调用。你不会致电ODataQueryOptions.ApplyTo。这是一个草图:

public IEnumerable<Thing> Get(ODataQueryOptions<Thing> opts)
{
    var filter = opts.Filter.FilterClause.Expression;
    var ordering = opts.OrderBy.OrderByClause.Expression;
    var skip = opts.Skip.Value;
    var top = opts.Top.Value;

    return this.Repository.GetThings(key, filter, ordering, skip, top);
}

请注意,上面的filterorderingMicrosoft.OData.Core.UriParser.Semantic.SingleValueNode的实例。该类有一个方便的Accept<T>方法,但您可能不希望您的存储库直接依赖该类。也就是说,您应该使用帮助程序来生成独立于Microsoft的OData实现的中间形式。

如果这是一种常见模式,请考虑使用parameter binding,以便直接从控制器方法的参数列表中获取各种查询选项。