让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,如需转载请自行联系原作者


相关文章
|
XML 数据格式 开发者
使用 Schema 的 sax 方式操作 xml(一)| 学习笔记
快速学习使用 Schema 的 sax 方式操作 xml。
使用 Schema 的 sax 方式操作 xml(一)| 学习笔记
|
XML 数据格式 开发者
使用 Schema 的 sax 方式操作 xml(二)| 学习笔记
快速学习使用 Schema 的 sax 方式操作 xml。
使用 Schema 的 sax 方式操作 xml(二)| 学习笔记
|
SQL Oracle Java
OR-Mapping 设计改进(结果集元数据) | 学习笔记
简介:快速学习 OR-Mapping 设计改进(结果集元数据)
|
SQL .NET
一起谈.NET技术,NHibernate3.0剖析:Query篇之NHibernate.Linq自定义扩展
  系列引入   NHibernate3.0剖析系列分别从Configuration篇、Mapping篇、Query篇、Session策略篇、应用篇等方面全面揭示NHibernate3.0新特性和应用及其各种应用程序的集成,基于NHibernte3.0版本。
1123 0
|
XML Java 数据库连接
Mybatis中的collection、association来处理结果映射
前不久的项目时间紧张,为了尽快完成原型开发,写了一段效率相当低的代码。 最近几天闲下来,主动把之前的代码优化了一下:)   标签:Java、Mybatis、MySQL 概况:本地系统从另外一个系统得到实体类集合List,但是实体中只有eventId信息,其他属性值均为空。
2047 0
|
SQL 算法 关系型数据库

热门文章

最新文章