OData是一个非常灵活的RESTful API,如果要做出强大的查询API,那么OData就强烈推荐了。http://www.odata.org/

OData的特点就是可以根据传入参数动态生成Entity Framework的查询,最终实现动态的SQL的查询。但是在项目有时我们并没有采用Entity Framework,而是采用的NHibernate,那么该怎么用OData呢?

经过一段时间的Google和研究,终于找到了一个好的方案。

在OData API查询时,用户前端是url跟参数,但是在服务器端,我们是接收到的是一个ODataQueryOptions<T>对象,其实我们需要做的就是把这个对象进行解析,生成NHibernate能够理解的查询形式,比如HQL。网上找到微软官方已经写了这么个转换方法,主要是对ODataQueryOptions对象下的Filter和OrderBy进行转换,另外两个参数Top和Skip很简单,就是一个整数。

public static string ToHql(this ODataQueryOptions query,out int top,out int skip) 
      { 
          string queryString = "from " + query.Context.ElementClrType.Name + " $it" + Environment.NewLine; 
          if (query.Filter != null) 
          { 
              // convert $filter to HQL where clause. 
              string where = ToString(query.Filter); 
              queryString += where; 
          } 
          if(query.OrderBy!=null) 
          { 
          // convert $orderby to HQL orderby clause. 
              string orderBy = ToString(query.OrderBy);
              // create a query using the where clause and the orderby clause. 
               queryString +=  orderBy; 
          } 
          top = query.Top?.Value ?? ; 
          skip = query.Skip?.Value ?? ; 
          return queryString; 
      } 

ODataQueryOptions转换为HQL的项目在这里:

http://aspnet.codeplex.com/SourceControl/changeset/view/72014f4c779e#Samples/WebApi/NHibernateQueryableSample/System.Web.Http.OData.NHibernate/NHibernateFilterBinder.cs

Filter和OrderBy属性都会被转换成HQL,然后我们就需要进行NHibernate的查询了。

public QueryResult<T> FindByPaging(string hql, int top, int skip) 
       { 
           bool paging = top > ; 
           var query = Session.CreateQuery(hql);
           var querys = Session.CreateMultiQuery(); 
           if (paging) 
           { 
               query = query.SetFirstResult(skip).SetMaxResults(top); 
           } 
           querys.Add(query); 
         
           if (paging) 
           { 
               var countQuery = Session.CreateQuery("select count(*) " + hql); 
               querys.Add(countQuery); 
           }
           var queryResults = querys.List(); 
           var result = new QueryResult<T>(); 
           result.TotalCount = paging 
               ? Convert.ToInt32( ((IList) queryResults[])[]) 
               : ((IList) queryResults[]).Count; 
           result.ResultSet = ((IList) queryResults[]).Cast<T>().ToList(); 
           return result; 
       } 

对于一般的分页查询来说,我们应该会有两个查询,一个是查询满足条件的数据总条数,另一个是返回当前页的数据集。但是似乎OData并不支持返回这样的数据类型,OData支持的是Entity的List,如果我们重新定义了一个对象QueryResult:

[DataContract] 
  public class QueryResult<T> 
  { 
      [DataMember] 
      public int TotalCount { get; set; } 
      [DataMember] 
      public IList<T> ResultSet { get; set; } 
      public QueryResult() 
      { } 
      public QueryResult(int count, IList<T> list) 
      { 
          this.TotalCount = count; 
          this.ResultSet = list; 
      } 
  } 

然后在Controller中返回QueryResult,那么系统就会报406的错误。其实系统给我们提供了一个专门分页返回的对象System.Web.Http.OData.PageResult<T>,我们可以将Service返回的QueryResult封装成PageResult再返回即可。

PageResult里面有个NextPage的URI参数,我们可以传Null。

让OData和NHibernate结合进行动态查询的更多相关文章

  1. Thinkphp查询 1.查询方式 2.表达式查询 3.快捷查询 4.区间查询 5.组合查询 6.统计查询 7.动态查询 8.SQL 查询

    1.使用字符串作为条件查询 $user = M('User'); var_dump($user->where('id=1 AND user="蜡笔小新"')->sele ...

  2. Linq 动态查询排序

    Linq的排序一般是这样写的: query.OrderBy(x => x.Tel).Skip().Take(); 实际使用中排序字段可能是通过字符类型的参数来设置的,于是想这样实现: query ...

  3. ibatis动态查询条件

    ibatis的调试相对困难,出错的时候主要依据是log4生成的log文件和出错提示,这方面要能比较熟练的看懂. 下面这个配置基本上包含了最复杂的功能:分页\搜索\排序\缓存\传值Hash表\返回has ...

  4. 自己写的一个关于Linq to Entity 动态查询的例子

    这两天一直想写一个动态查询的方式,先是晚上查询了一下,发现大家写的差不多都是一样的[如:http://www.cnblogs.com/ASPNET2008/archive/2012/10/28/274 ...

  5. Linq动态查询简易解决之道(原创)

    因为项目需要使用Linq来查询数据,但是在多条件查询时,需要使用一大堆if(...!=string.empty)等判断条件感觉不是很优雅.网上搜索以下,大概找到了两种办法,一种是老外写的一个类,感觉用 ...

  6. SSH动态查询封装接口介绍

    SSH动态查询封装接口介绍 1.查询记录总条数 public int count(Class c,Object[][] eq,Object[][] like,String[] group,String ...

  7. Linq to sql 实现多条件的动态查询(方法一)

    /// <summary> /// Linq to sql 多字段动态查询 /// </summary> /// <returns></returns> ...

  8. Linq to Sql : 动态构造Expression进行动态查询

    原文:Linq to Sql : 动态构造Expression进行动态查询 前一篇在介绍动态查询时,提到一个问题:如何根据用户的输入条件,动态构造这个过滤条件表达式呢?Expression<Fu ...

  9. Linq to Sql:N层应用中的查询(下) : 根据条件进行动态查询

    原文:Linq to Sql:N层应用中的查询(下) : 根据条件进行动态查询 如果允许在UI层直接访问Linq to Sql的DataContext,可以省去很多问题,譬如在处理多表join的时候, ...

随机推荐

  1. 创建DbContext

    返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 上一篇介绍了<创建实体>,这一篇我们顺其自然地介绍<创建DbContext>. 温故: 提到DbConte ...

  2. C++ std::map

    std::map template < class Key, // map::key_type class T, // map::mapped_type class Compare = less ...

  3. Rxjava cold/hot Observable

    create Observable分为cold以及hot两种,cold主要是静态的,每次subscribe都是从头开始互不干扰,而hot的在同一时刻获得的值是一致的 cold Observable 使 ...

  4. spring声明式事务管理总结

    事务配置 首先在/WEB-INF/applicationContext.xml添加以下内容: <!-- 配置事务管理器 --> <bean id="transactionM ...

  5. 解析大型.NET ERP系统 数据审计功能

    数据审计,英语表达是Audit,是追踪数据变化的过程,记录数据变化前后的值,供参考分析.通过设置,ERP可以追踪一个表的所有字段的变化,也可以只记录指定的字段的值变化.欧美企业每年都有独立的审计部门, ...

  6. Hawk 2. 软件界面介绍

    2. 软件界面介绍 1. 基本组件 Hawk采用类似Visual Studio和Eclipse的Dock风格,所有的组件都可以悬停和切换.包括以下核心组件: 左上角区域:主要工作区,任务管理. 下方: ...

  7. Reactor by Example--转

    原文地址:https://www.infoq.com/articles/reactor-by-example Key takeaways Reactor is a reactive streams l ...

  8. Vertica DBD 分析优化设计

    DBD = Database Designer,是Vertica数据库优化中最主要的原生工具. 首先运行admintools工具,按下面步骤依次执行: 1.选择"6 Configuratio ...

  9. 使用java传参调用exe并且获取程序进度和返回结果的一种方法

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 在某个项目中需要考虑使用java后台调用由C#编写的切图程序( ...

  10. 外边距塌陷之clearance

    在一个BFC中,垂直方向上相邻的块级盒子产生外边距塌陷,本文要说一个特殊的外边距塌陷情况,即当垂直方向上,两个块级盒子之间有个浮动元素相隔时,这个时候会产生什么样的效果呢? .outer{ overf ...