让OData和NHibernate结合进行动态查询

简介:

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 ??  0
          skip = query.Skip?.Value ??  0
           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 >  0
            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[ 1])[ 0]) 
               : ((IList) queryResults[ 0]).Count; 
           result.ResultSet = ((IList) queryResults[ 0]).Cast<T>().ToList(); 
            return result; 
       } 

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

[DataContract] 
   public  class QueryResult<T> 
  { 
      [DataMember] 
       public  int TotalCount {  getset; } 
      [DataMember] 
       public IList<T> ResultSet {  getset; } 
       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。 

本文转自深蓝居博客园博客,原文链接:http://www.cnblogs.com/studyzy/p/5462868.html,如需转载请自行联系原作者


相关文章
|
7月前
|
SQL 测试技术 容器
使用 ABAP 代码给 OData 元数据增添注解的一些例子
使用 ABAP 代码给 OData 元数据增添注解的一些例子
31 0
|
7月前
SAP ABAP OData 服务如何支持 $filter (过滤)操作试读版
SAP ABAP OData 服务如何支持 $filter (过滤)操作试读版
65 0
|
缓存
SAP Fiori OData gateway 和后台 ABAP 系统的双缓存表(cache table)设计
SAP Fiori OData gateway 和后台 ABAP 系统的双缓存表(cache table)设计
136 0
SAP Fiori OData gateway 和后台 ABAP 系统的双缓存表(cache table)设计
SAP CDS view生成的OData服务对CRUD(增删改查)的支持
SAP CDS view生成的OData服务对CRUD(增删改查)的支持
224 0
SAP CDS view生成的OData服务对CRUD(增删改查)的支持
|
小程序 Windows
SAP C4C OData服务的filter,客户端分页和排序的使用方式
假设系统里已经有许多的Lead历史数据,而我们正在进行的微信小程序和C4C集成的项目里,又创建了许多新的Lead数据。如何将这些新的在微信小程序里调用OData服务创建的Lead数据同老的历史数据做区分呢? (1) 在C4C Sales Lead页面里,通过Source字段来标明Lead的来源。
SAP C4C OData服务的filter,客户端分页和排序的使用方式
|
Go 数据库
SAP ABAP数据库表字段checktable的实现原理
SAP ABAP数据库表字段checktable的实现原理
166 0
SAP ABAP数据库表字段checktable的实现原理