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中的一对多关 ...
随机推荐
- LINUX 内核2
http://blog.csdn.net/acs713/article/category/1363650
- requestFileSystem is undefined
使用phonegap 3时,用File API,不应该用cordova plugin add org.apache.cordova.file等添加File API Plugin. 要用: phoneg ...
- 小白日记10:kali渗透测试之端口扫描-UDP、TCP、僵尸扫描、隐蔽扫描
端口扫描 二三四层发现的目的只是为了准确发现所有活着主机IP,确定攻击面,端口扫描即发现攻击点,发现开放端口.端口对应网络服务及应用端程序,服务端程序的漏洞通过端口攻入.[所有的扫描结果,都不要完全相 ...
- const ;static;extern的使用与作用
const /** const :常量 const ...
- linux编辑器 vi的使用
vi 编辑器的三个模式: 命令模式 开始就是命令模式 insert模式 i, I, a, A, o,O ,s, S 命令行模式 : i 在当前位置进入Insert模式 I 在行的头部进入Inser ...
- javaweb学习总结十九(http协议概述以及http请求信息分析)
一:http协议概述 1:http协议定义 2:使用telnet程序连接web服务器,获取资源 3:http协议:超文本传输协议,它是基于tcp/ip协议,就是建立在tcp/ip之上工作的, http ...
- Android自动化测试介绍
1.随机事件测试.通过adb命令执行测试Monkey 就是SDK中附带的一个工具, 用来做压力测试.应用程序crash 和 ANR时会产生日志. 然后根据关键字分析,就可以把应用出现的问题抓出来. 2 ...
- oracle 9i 中行转列
示例如下: SELECT deptno , LTRIM(MAX(SYS_CONNECT_BY_PATH(ename,',')) KEEP (DENSE_RANK LAST ORDER BY curr) ...
- asp.net mvc 的几种分页Pager
第一种 /// <summary> /// 分页Pager显示 /// </summary> /// <param name="html">&l ...
- MyBatis(3.2.3) - One-to-many mapping
In the sample domain model, a tutor can teach one or more courses. This means that there is a one-to ...