【问题标题】:Parsing ODataQueryOptions<type> without EF/Nhibernate在没有 EF/Nhibernate 的情况下解析 ODataQueryOptions<type>
【发布时间】:2016-03-13 17:35:45
【问题描述】:

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

有没有办法从这个东西中得到一个 AST,我可以把它变成 sql 代码?

【问题讨论】:

  • 底层数据库技术是什么?它可能已经有一个查询提供程序,特别是如果它的查询语言是 SQL。
  • 经典 ADO.net over sql server,带有使用 T4 模板生成的瘦包装层。没有 LINQ 提供程序,因为所有调用都通过存储过程。同义词、层次结构和尝试使用表值参数存在很多问题,这使得我们开始时无法使用 EF。如果我能避免的话,现在真的不在乎把它带进来。
  • 从好的方面来说,我不需要预测/分组。只是简单的过滤、分页和排序。

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


【解决方案1】:

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

祝你好运!

【讨论】:

    【解决方案2】:

    您可以使用ODataQueryOptions&lt;T&gt; 获取$filter$orderby 查询选项的抽象语法树。 ($skip$top 也可作为解析整数使用。)由于您不需要/想要 LINQ 支持,因此您可以简单地将 AST 传递给存储库方法,然后访问 AST 以构建适当的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&lt;T&gt; 方法,但您可能不希望您的存储库直接依赖于该类。也就是说,您可能应该使用帮助程序来生成独立于 Microsoft 的 OData 实现的中间表单。

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

    【讨论】:

      猜你喜欢
      • 2011-08-23
      • 1970-01-01
      • 1970-01-01
      • 2021-12-19
      • 2020-03-03
      • 2021-04-19
      • 2023-03-04
      • 2012-03-27
      • 1970-01-01
      相关资源
      最近更新 更多