让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 ?? ;
skip = query.Skip?.Value ?? ;
return queryString;
}
ODataQueryOptions转换为HQL的项目在这里:
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结合进行动态查询的更多相关文章
- Thinkphp查询 1.查询方式 2.表达式查询 3.快捷查询 4.区间查询 5.组合查询 6.统计查询 7.动态查询 8.SQL 查询
1.使用字符串作为条件查询 $user = M('User'); var_dump($user->where('id=1 AND user="蜡笔小新"')->sele ...
- Linq 动态查询排序
Linq的排序一般是这样写的: query.OrderBy(x => x.Tel).Skip().Take(); 实际使用中排序字段可能是通过字符类型的参数来设置的,于是想这样实现: query ...
- ibatis动态查询条件
ibatis的调试相对困难,出错的时候主要依据是log4生成的log文件和出错提示,这方面要能比较熟练的看懂. 下面这个配置基本上包含了最复杂的功能:分页\搜索\排序\缓存\传值Hash表\返回has ...
- 自己写的一个关于Linq to Entity 动态查询的例子
这两天一直想写一个动态查询的方式,先是晚上查询了一下,发现大家写的差不多都是一样的[如:http://www.cnblogs.com/ASPNET2008/archive/2012/10/28/274 ...
- Linq动态查询简易解决之道(原创)
因为项目需要使用Linq来查询数据,但是在多条件查询时,需要使用一大堆if(...!=string.empty)等判断条件感觉不是很优雅.网上搜索以下,大概找到了两种办法,一种是老外写的一个类,感觉用 ...
- SSH动态查询封装接口介绍
SSH动态查询封装接口介绍 1.查询记录总条数 public int count(Class c,Object[][] eq,Object[][] like,String[] group,String ...
- Linq to sql 实现多条件的动态查询(方法一)
/// <summary> /// Linq to sql 多字段动态查询 /// </summary> /// <returns></returns> ...
- Linq to Sql : 动态构造Expression进行动态查询
原文:Linq to Sql : 动态构造Expression进行动态查询 前一篇在介绍动态查询时,提到一个问题:如何根据用户的输入条件,动态构造这个过滤条件表达式呢?Expression<Fu ...
- Linq to Sql:N层应用中的查询(下) : 根据条件进行动态查询
原文:Linq to Sql:N层应用中的查询(下) : 根据条件进行动态查询 如果允许在UI层直接访问Linq to Sql的DataContext,可以省去很多问题,譬如在处理多表join的时候, ...
随机推荐
- dhcp协议交互报文
DHCP共有八种报文,分别为DHCP Discover.DHCP Offer.DHCP Request.DHCP ACK.DHCP NAK.DHCP Release.DHCP Decline.DHCP ...
- xcode低版本调试高版本真机系统
低版本xcode调试本真机高版本系统 //打开此路径把最新的文件拷贝到这里就可以了 /Applications/Xcode.app/Contents/Developer/Platforms/iPhon ...
- 本地存储之cookie
cookie概述: Cookie 在计算机中是个存储在浏览器目录中的文本文件,当浏览器运行时,存储在 RAM 中发挥作用 (此种 Cookies 称作 Session Cookies), 一旦用户从该 ...
- SSIS 属性:ExecValueVariable
有些Task组件执行完成之后,会产生输出结果,称作Execution Value,例如,Execute SQL Task在执行完成之后,会返回受影响的数据行数.Task组件的Execution Val ...
- Windows 10 部署Enterprise Solution 5.5
Windows 10正式版发布以后,新操作系统带来了许多的变化.现在新购买的电脑安装的系统应该是Windows 10.与当初用户不习惯Windows 7,购买新电脑后第一个想做的事情就是重装成XP,估 ...
- Enterprise Solution 生成实体数据访问接口与实现类型 Code Smith 6.5 模板文件下载
数据库表定义为SalesOrder,用LLBL Gen Pro生成的实体定义是SalesOrderEntity,再用Code Smith生成的数据读写接口是ISalesOrderManager,最后是 ...
- 前端MVVM框架设计及实现
最近抽出点时间想弄个dom模块化的模板引擎,不过现在这种都是MVVM自带的,索性就想自己造轮子写一个简单的MVVM框架了 借鉴的自然还是从正美的Avalon开始了,我2013年写过一个关于MVC MV ...
- JavaScript权威设计--命名空间,函数,闭包(简要学习笔记十二)
1.作为命名空间的函数 有时候我们需要声明很多变量.这样的变量会污染全局变量并且可能与别人声明的变量产生冲突. 这时.解决办法是将代码放入一个函数中,然后调用这个函数.这样全局变量就变成了 局部变量. ...
- egret3D与2D混合开发,画布尺寸不一致的问题
egret3d的GUI目前还没有,在做3d游戏的时候没有UI可用,只能使用egret2d的EUI组件库,egret3d与egret2d混合开发,canvas3d的大小与位置与canvas2d并没有重合 ...
- 【NLP】揭秘马尔可夫模型神秘面纱系列文章(三)
向前算法解决隐马尔可夫模型似然度问题 作者:白宁超 2016年7月11日22:54:57 摘要:最早接触马尔可夫模型的定义源于吴军先生<数学之美>一书,起初觉得深奥难懂且无什么用场.直到学 ...