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


相关文章
|
SQL 关系型数据库 MySQL
MySQL-主从架构的搭建
MySQL-主从架构的搭建
431 0
|
5月前
|
人工智能 网络协议 API
开发效率翻倍!Apipost这些协议调试秘籍,从HTTP到金融报文全搞定
Apipost是一款强大的API研发管理工具,支持多种协议与数据格式,包括HTTP(s)、WebSocket、SSE、gRPC、TCP及金融协议(如ISO 8583、FIX)。它内置国密算法库,提供HTTP文件秒传、全局参数配置等实用功能。在SSE调试中,可轻松处理AI模型流式响应;WebSocket与Socket.IO实现高效实时通信;GraphQL支持可视化Query编写;TCP模块解决金融报文编码难题;gRPC则具备服务反射与流式调试能力。Apipost不仅简化了多协议切换的复杂性,还自动生成文档,显著提升开发效率,让开发者专注于核心业务逻辑。
|
10月前
|
机器学习/深度学习 自然语言处理 监控
CNN的应用场景
【10月更文挑战第23天】CNN的应用场景
693 3
|
11月前
|
数据库 索引
联合索引和单独列索引哪个更好
【10月更文挑战第15天】联合索引和单独列索引哪个更好
389 2
|
11月前
|
存储 移动开发 关系型数据库
HarmonyOS 鸿蒙面试第一弹
HarmonyOS 鸿蒙面试第一弹
|
存储 算法 安全
深入理解Linux命令pwscore:密码质量的守护者
**pwscore命令详解:Linux密码强度评估工具** pwscore是Linux下的密码强度检查工具,分析密码长度、字符类型及避免常见模式来评分。它提供简单语法、可定制选项和高效评估。例如,`pwscore -l 12 -m alnum`评估至少含12个字符和字母数字的密码。应用时,定期评估用户密码,制定强密码策略,避免常见单词和模式,使用密码管理器,并保护输出信息安全,以增强系统安全性。
|
NoSQL 网络安全 Redis
【docker】部署的redis突然连接不上了
【docker】部署的redis突然连接不上了
390 2
|
存储 监控 Docker
如何限制docker使用的cpu,内存,存储
如何限制docker使用的cpu,内存,存储
|
JSON 小程序 数据格式
|
存储 关系型数据库 MySQL
在 MySQL 中使用创建临时表
【8月更文挑战第11天】
1539 0
在 MySQL 中使用创建临时表