让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的时候, ...
随机推荐
- Java 8函数编程轻松入门(四)方法引用
C#中系统提供了许多IEnumerable的扩展方法.同样在Java 8中新引入了Collector类. 1.方法引用 定义: 简而言之:就是一个Lambda表达式.在Java 8中,我们我们会使用L ...
- 浅析Java 泛型
泛型是JavaSE5引入的一个新概念,但是这个概念在编程语言中却是很普遍的一个概念.下面,根据以下内容,我们总结下在Java中使用泛型. 泛型使用的意义 什么是泛型 泛型类 泛型方法 泛型接口 泛型擦 ...
- BoneCP 升级遇到的问题
Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [c ...
- lr文件下载脚本(文件参数化重命名)
http://wenku.baidu.com/link?url=6oiIadyF9eFS4VshKbfJDnxrBh2IX919ndi0JO8yoqTRNRNIpavFrZJ9LPVb-FBSfbRY ...
- Java环境变量-Linux环境
环境变量说明 JAVA_HOME 它指向jdk的安装目录,Eclipse/NetBeans/Tomcat等软件就是通过搜索JAVA_HOME变量来找到并使用安装好的jdk. PATH 作用是指定命令搜 ...
- 了解HTML图像
img <img>表示image图像,从技术上讲,<img>标签并不会在网页中插入图像,而是从网页上链接图像.<img> 标签创建的是被引用图像的占位空间. [必须 ...
- JavaScript动画-模拟拖拽
模拟拖拽的原理: x1等于div.offsetLeft y1等于div.offsetTop x2等于ev.clientX(ev表示event事件) y2等于ev.clientY 当我们在方块上按下鼠标 ...
- 浅析JavaScript事件流——冒泡
一.什么是事件冒泡流 我们知道事件流指的是从页面中接受事件的顺序. 为了形象理解事件冒泡,可以想象三军主将诸葛亮,在帐内运筹帷幄,眼观六路耳听八方,这时候前方的战事情况就需要靠传令兵来传达,当第一位传 ...
- Grunt学习使用
原文地址:Grunt学习使用必看 grunt简介神马的不多说,到处一大堆. 我只说说我已经实现了的代码. 按照官方的教程 相信已经配置好了,接下来说 package.json 和 Gruntfile. ...
- 使用F#开发ASP.NET Core应用程序
.NET Core 里的F# 在.NET Core刚发布时,就已经添加了对F#的支持.但因为当时F#组件还不完整,而一些依赖包并没有放在Nuget上,而是社区自己放到MyGet上,所以在使用dotne ...