NHibernate各种查询
NHibernate's methods of querying are powerful, but there's a learning curve. Longer term, Linq is the way to go, although it may not be as capable as Linq2Sql or Entity Framework (Hql and Criteria are arguably superior for advanced scenarios anyway).
- Get by primary key is built-in (session.Get and session.Load; latter loads a proxy which only does the database select when needed).
- HQL - a provider-neutral Sql-like language. Unfortunately it's just a big string. It's good for ststic queries and has the most advanced capabilities.
- Criteria - more object like and good for building dynamic runtime queries. Property names are still strings.
- QueryOver - (NHibernate 3+) uses lambdas over Criteria to make it strongly typed.
- Linq -
- In NHibernate 2 and 2.1, this is a NHibernate Contrib extension (as ISession.Linq<T>). You need to get the source and rebuild against the latest NHibernate 2.1 version. It works well for simple queries.
- From NHibernate 3.0, Linq is part of the NHibernate core (as ISession.Query<T>) and gives more advanced features, although not everything may be there.
Lists with restrictions
//directly get by id (see also Load<> - loads proxy)
var category = session.Get<Category>(2);
//hql
var hqlQuery = session.CreateQuery("from Product p where p.Category.Id = ? order by p.Id")
//set the parameter
.SetInt32(0, 2)
//second page of 10
.SetFirstResult(10).SetMaxResults(10);
var list = hqlQuery.List<Product>();
//criteria
var criteria = session.CreateCriteria<Product>()
//"Restrictions" used to be "Expression"
.Add(Restrictions.Eq("Category.Id", 2))
//ordering
.AddOrder(NHibernate.Criterion.Order.Asc("Id"))
//paging, 2nd page of 10
.SetFirstResult(10) //zero based
.SetMaxResults(10);
var list2 = criteria.List<Product>();
//query over
var queryOver = session.QueryOver<Product>()
.Where(x => x.Category.Id == 2)
//simple restrictions- And or &&/||
//.And(x => !x.Discontinued)
//.And(x => !x.Discontinued && x.UnitsInStock > 0)
.OrderBy(x => x.Id).Asc
.Skip(10)
.Take(10);
var list3 = queryOver.List();
//using NHibernate.Linq (session.Linq in NH 2/session.Query in NH3)
var linq = (from product in session.Query<Product>()
where product.Category.Id == 2
orderby product.Id
select product)
.Skip(10)
.Take(10);
var list4 = linq.ToList();
Single Results
//HQL counts
var hqlCountQuery = session.CreateQuery("select count(*) from Product p where p.Category.Id = ?")
.SetInt32(0, 2);
var count1 = hqlCountQuery.UniqueResult<long>(); //always a long
//criteria counts
var countCriteria = session.CreateCriteria<Product>()
//add rowcount projection - NB: RowCountInt64 for long
.SetProjection(Projections.RowCount())
.Add(Restrictions.Eq("Category.Id", 2));
var count2 = countCriteria.UniqueResult<int>();
//queryOver counts
var count3 = session.QueryOver<Product>()
.Where(x => x.Category.Id == 2)
.RowCount();
//linq counts
var count4 = session.Query<Product>().Count(p => p.Category.Id == 2);
MultiQuery
You can batch multiple queries in a single call. The Hql equivalent would use Multiquery; Criteria uses MultiCriteria.
//you can also use separate ICriterias with .Future / .FutureValue
IMultiCriteria multiCriteria = s.CreateMultiCriteria()
.Add<Product>(
s.CreateCriteria<Product>()
//"Restrictions" used to be "Expression"
.Add(Restrictions.Eq("Category.Id", 2))
//ordering
.AddOrder(NHibernate.Criterion.Order.Asc("Id"))
//paging, 2nd page of 10
.SetFirstResult(10) //zero based
.SetMaxResults(10)
)
.Add(
s.CreateCriteria<Product>()
//add rowcount projection - NB: RowCountInt64 for long
.SetProjection(Projections.RowCount())
.Add(Restrictions.Eq("Category.Id", 2))
)
;
var criteriaResults = multiCriteria.List();
IList<Product> products = (IList<Product>)criteriaResults[0];
int criteriaCount = (int)((IList)criteriaResults[1])[0];
Joins
In criteria, use a nested criteria or alias.
//no join, it knows Id is on Product
var list1 = session.CreateCriteria<Product>()
.Add(Restrictions.Eq("Discontinued", false))
.Add(Restrictions.Eq("Category.Id", 2))
.List<Product>();
//for any other category properties create nested criteria
var list2 = session.CreateCriteria<Product>()
.Add(Restrictions.Eq("Discontinued", false))
.CreateCriteria("Category")
.Add(Restrictions.Eq("CategoryName", "Condiments"))
.List<Product>();
//use alias to flatten
var list4 = session.CreateCriteria<Product>()
.Add(Restrictions.Eq("Discontinued", false))
.CreateAlias("Category", "c")
.Add(Restrictions.Eq("c.CategoryName", "Condiments"))
.List<Product>();
//queryOver with join
var qover = session.QueryOver<Product>()
.Where(x => !x.Discontinued)
.JoinQueryOver(x => x.Category)
.Where(c => c.CategoryName == "Condiments")
.List();
//queryOver with join and aliases
Product productAlias = null; //you need null objects
Category categoryAlias = null;
var qoAlias = session.QueryOver(() => productAlias)
.JoinQueryOver(x => x.Category, () => categoryAlias)
//you can use the simple
.Where(() => categoryAlias.CategoryName == "Condiments")
.And(() => !productAlias.Discontinued)
.List();
//linq
var linq = (from product in session.Query<Product>()
join category in session.Query<Category>()
on product.Category.Id equals category.Id
where category.CategoryName == "Condiments"
&& !product.Discontinued
select product).ToList();
Subqueries
//with HQL
var hqlList = session.CreateQuery(
@"from Product p where p.Id in
(select n.Id from Product n
where (n.UnitsInStock = :units
or n.Discontinued = :dis))
and p.Category.Id = :cat")
.SetInt16("units", (short)0)
.SetBoolean("dis", true)
.SetInt32("cat", 2)
.List<Product>();
//with Criteria and DetachedCriteria
var notForSale = DetachedCriteria.For<Product>("noSale")
//for subquery you must project
.SetProjection(Projections.Property("noSale.id"))
.Add(Restrictions.Disjunction()
.Add(Restrictions.Eq("noSale.UnitsInStock", (short)0))
.Add(Restrictions.Eq("noSale.Discontinued", true)))
.Add(Restrictions.Eq("Category.Id", 2));
var criteriaList = session.CreateCriteria<Product>()
//the id must be in our subquery select
.Add(Subqueries.PropertyIn("Id",notForSale))
.List<Product>();
//with QueryOver (NH3)
var detachedQueryOver = QueryOver.Of<Product>()
//you can .And or use simple expressions with && and ||
.Where(x => x.UnitsInStock == 0 || x.Discontinued)
.And(x=> x.Category.Id == 2)
.Select(x => x.Id) //simple projection
;
var queryOverList = session.QueryOver<Product>()
.WithSubquery
.WhereProperty(x => x.Id)
.In(detachedQueryOver)
.List();
//NH Linq doesn't support subqueries :(
var linq = from product in session.Query<Product>()
where
(product.Discontinued
|| product.UnitsInStock == 0)
&& product.Category.Id == 2
select product;
Projecting to a DTO
See above for projections for aggregations such as counts. The generated SQL only selects the required columns- not everything. The Transformers.AliasToBean is an ugly relic of the port from Java.
var proj = Projections.ProjectionList()
//projected mapped class property to alias of dto property
.Add(Projections.Property("ProductName"), "ProductName")
.Add(Projections.Property("c.CategoryName"), "CategoryName")
.Add(Projections.Property("UnitsInStock"), "Units");
var result = session.CreateCriteria<Product>("p")
.Add(Restrictions.Gt("UnitPrice", 10m))
.CreateAlias("Category", "c")
.Add(Restrictions.Eq("Category.Id", 2))
.SetProjection(proj)
.SetResultTransformer(
NHibernate.Transform.Transformers.AliasToBean(typeof(Northwind.Dto.ProductLite)))
.List<Northwind.Dto.ProductLite>();
In Hql, you can either have fun with object arrays, or you have to use a mappings import on the DTO.
IList results = session.CreateQuery(
@"select p.ProductName, c.CategoryName, p.UnitsInStock
from Product p join p.Category c
where p.UnitPrice > 10 and c.Id = 2").List();
foreach (object[] row in results)
{
string name = (string)row[0];
string category = (string)row[1];
var units = (short)row[2];
var dto = new Northwind.Dto.ProductLite(name, category, units);
}
//need to import it
//<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
// <import class="Northwind.Dto.ProductLite, Northwind" />
//</hibernate-mapping>
var results2 = session.CreateQuery(
@"select new ProductLite(p.ProductName, c.CategoryName, p.UnitsInStock)
from Product p join p.Category c
where p.UnitPrice > 10 and c.Id = 2")
.List<Northwind.Dto.ProductLite>();
转载地址:http://www.cnblogs.com/ylwn817/articles/1963528.html
NHibernate各种查询的更多相关文章
- [NHibernate]HQL查询
目录 写在前面 文档与系列文章 查询的几种方式 HQL查询 一个例子 总结 写在前面 上篇文章介绍了nhibernate在项目中的基本配置,包括数据库连接字符串的设置,映射文件的配置及需注意的地方,这 ...
- [NHibernate]条件查询Criteria Query
目录 写在前面 文档与系列文章 条件查询 一个例子 总结 写在前面 上篇文章介绍了HQL查询,我个人觉得使用ORM框架就是为了让少些sql,提高开发效率,而再使用HQL就好像还是使用sql,就觉得有点 ...
- NHibernate 数据查询之QueryOver<T>
NHibernate 数据查询之QueryOver<T> 一.限制运算符 Where:筛选序列中的项目WhereNot:反筛选序列中的项目 二.投影运算符 Select:创建部分序列的 ...
- NHibernate 数据查询之Linto to NHibernate (第八篇)
NHibernate 数据查询之Linto to NHibernate (第八篇) 刚学NHibernate的时候觉得,HQL挺好用的,但是终归没有与其他技术 相关联,只有NHibernate用到,一 ...
- NHibernate - ICriteria 查询
http://blog.knowsky.com/213234.htm http://blog.chinaunix.net/uid-20463341-id-1673509.html http://www ...
- NHibernate 数据查询之Linq to NHibernate
刚学NHibernate的时候觉得,HQL挺好用的,但是终归没有与其他技术相关联,只有NHibernate用到,一来容易忘记,二来没有智能提示,排除错误什么的都不给力,直到看到一个同事用Linq to ...
- NHibernate Linq查询 扩展增强 (第九篇)
在上一篇的Linq to NHibernate的介绍当中,全部是namespace NHibernate命名空间中的IQueryOver<TRoot, TSubType>接口提供的.IQu ...
- 让OData和NHibernate结合进行动态查询
OData是一个非常灵活的RESTful API,如果要做出强大的查询API,那么OData就强烈推荐了.http://www.odata.org/ OData的特点就是可以根据传入参数动态生成Ent ...
- [NHibernate]一对多关系(关联查询)
目录 写在前面 文档与系列文章 一对多查询 总结 写在前面 上篇文章介绍了nhibernate的一对多关系如何配置,以及级联删除,级联添加数据的内容.这篇文章我们将学习nhibernate中的一对多关 ...
随机推荐
- CSS文字大小单位px、em、pt(转)
这里引用的是Jorux的“95%的中国网站需要重写CSS”的文章,题目有点吓人,但是确实是现在国内网页制作方面的一些缺陷.我一直也搞不清楚px与em之间的关系和特点,看过以后确实收获很大.平时都是用p ...
- Python基础教程之List对象 转
Python基础教程之List对象 时间:2014-01-19 来源:服务器之家 投稿:root 1.PyListObject对象typedef struct { PyObjec ...
- 【ZZ】Java : 一个帝国的诞生 & 假如时光能够倒流, 我会这么学习Java
Java : 一个帝国的诞生 http://dy.qq.com/article.htm?id=20160523A06XFS00 写的很有意思,一下子了解了JAVA的历史. 假如时光能够倒流, 我会这么 ...
- C语言之指针与数组总结
和指针相关的问题口诀1: 1. 地址变量得地址,得谁地址指向谁 和指针相关的问题要画图: 内容变量画房子,指针画箭头 ---->口 ------------------------------- ...
- Java基础知识强化之集合框架笔记75:哈希表
1. 哈希表数据结构(数组): 2. 哈希表确定元素是否相同: (1)判断的是两个元素的哈希值是否相同 如果相同,再判断两个对象内容是否相同 (2)判断哈希值相 ...
- 为什么arcgis里,鼠标的图标都变成放大镜不能用了
做作业做到一半,鼠标的图标就只有放大镜了,不管是点箭头还是作图工具都没用,手抓的也没用,只剩下放大镜的功能和图标了,这是怎么一回事啊?种情况我碰到过几次,具体原因不清楚,但是解决方法是有的:把你的数据 ...
- C#动态引用DLL的方法
C#编程中,使用dll调用是经常的事,这样做的好处是非常多的,比如把某些功能封装到一个dll中,然后主程序动态调用这个dll. 废话不多说,举例说明如下. 首先,我们需要封装一个dll,vs2008下 ...
- Linux parted 分区
转自http://tilt.lib.tsinghua.edu.cn/node/889 如何使用parted对齐分区以得到最优性能 Sat, 03/08/2014 - 18:02 - tlblues ...
- 移植最新u-boot(裁剪和修改默认参数)之韦东山笔记
1.下载.建立source insight工程.编译.烧写.如果无运行分析原因 tar xjf u-boot-2012.04.01.tar.bz2 cd u-boot-2012.04.01 make ...
- 慕课网,我的yii2学习笔记(基础篇)
一.关于PHP知识点 1.命名空间:存放类文件的空间,可以随便定义,建议与类文件目录一致,方便管理. 注:(1).如果类没有设置命名空间,默认为顶级命名空间,在程序中可以用一下方式实例化. $mode ...