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中的一对多关 ...
随机推荐
- PAT 1004
1004. Counting Leaves (30) A family hierarchy is usually presented by a pedigree tree. Your job is t ...
- zend studio 函数不提醒 小黄图标 小黄标
在用 Zend Studio 编写 PHP 项目时发现调用系统函数时调试正常, 但是在编写代码时却提示函数未定义"Call to undefined function ", 在左侧 ...
- iOS利用单例实现不同界面间的数据传输
首先写一个单例类,继承NSObject check.h文件中 @property(strong ,nonatomic) UITable * Table; @property(strong ,nonit ...
- graylog2+syslog-ng+mongodb构建集中管理日志服务器 --转载
原文地址:http://blog.chinaunix.net/uid-11065483-id-3654882.html 由于公司内需要监控QQ的上下线记录,原本使用了分光+Panabit+Splunk ...
- How to solve Original Tango programmer”Hardware not Found”?
Original Tango programmer is a new generation of transponder programmer which is developed to cover, ...
- 协议Protocol
1.协议:是一组声明方法的集合,不能声明成员变量,作用类似于接口. 遵守此协议的类就相当于拥有了这个协议的所有方法的声明,如果父类遵守了某个协议,子类也遵守了这个协议. ...
- 安装 tomat
(1)新建一个文件夹放置要下载的tomcat: mkdir /software 进入software目录 cd /software (2)下载tomcat放置在software目录下 wget ht ...
- python(3)-lambda表达式
>>> fun = lambda a: a+1 >>> fun(1) 2 >>> fun = lambda a,b: a+b >>&g ...
- CF Anya and Ghosts (贪心)
Anya and Ghosts time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...
- [改善Java代码]Lock与synchronized是不一样的
很多编码者都会还说,Lock类和synchronized关键字用在代码块的并发性和内存上时语义是一样的.