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


相关文章
|
5月前
|
SQL 存储 开发框架
【Entity Framework】你必须了解的之自定义SQL查询
【Entity Framework】你必须了解的之自定义SQL查询
87 0
|
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版本。
1115 0
|
.NET API 索引
一起谈.NET技术,NHibernate3.0剖析:Query篇之NHibernate.Linq标准查询
  系列引入   NHibernate3.0剖析系列分别从Configuration篇、Mapping篇、Query篇、Session策略篇、应用篇等方面全面揭示NHibernate3.0新特性和应用及其各种应用程序的集成,基于NHibernte3.0版本。
1273 0
|
缓存
一起谈.NET技术,NHibernate3.0剖析:Query篇之NHibernate.Linq增强查询
  相关文章:NHibernate3.0剖析:Query篇之NHibernate.Linq标准查询   系列引入   NHibernate3.0剖析系列分别从Configuration篇、Mapping篇、Query篇、Session策略篇、应用篇等方面全面揭示NHibernate3.0新特性和应用及其各种应用程序的集成,基于NHibernte3.0版本。
1002 0
|
SQL .NET C#
一起谈.NET技术,Linq to SQL T4 代码生成器 (二)访问设计器中的 Table 对象
  在上一篇文章中,介绍了如何访问 DataContext 对象,下面接着来讲解一下如何访问设计器中的表对象,并生成生体类代码。从 Northwind 数据库中拖一个表到设计器中。拖出来后,记得保存 dbml 文件,否则是无法访问到这个表的。
1038 0
|
存储 缓存 数据库
ORM映射框架总结--实体分析器
1.       什么是数据分析器 前面一篇文章讲到过数据分析器,什么是数据分析器。其实很容易理解,就是对数据进行分析采集的一个工具,说白了就是一个小程序,在本ORM框架中对实体对象进行必要的数据分析,获得实体对象的各种信息缓存,以便在后续的工作中直接提取数据。
775 0