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各种查询的更多相关文章

  1. [NHibernate]HQL查询

    目录 写在前面 文档与系列文章 查询的几种方式 HQL查询 一个例子 总结 写在前面 上篇文章介绍了nhibernate在项目中的基本配置,包括数据库连接字符串的设置,映射文件的配置及需注意的地方,这 ...

  2. [NHibernate]条件查询Criteria Query

    目录 写在前面 文档与系列文章 条件查询 一个例子 总结 写在前面 上篇文章介绍了HQL查询,我个人觉得使用ORM框架就是为了让少些sql,提高开发效率,而再使用HQL就好像还是使用sql,就觉得有点 ...

  3. NHibernate 数据查询之QueryOver<T>

    NHibernate 数据查询之QueryOver<T>   一.限制运算符 Where:筛选序列中的项目WhereNot:反筛选序列中的项目 二.投影运算符 Select:创建部分序列的 ...

  4. NHibernate 数据查询之Linto to NHibernate (第八篇)

    NHibernate 数据查询之Linto to NHibernate (第八篇) 刚学NHibernate的时候觉得,HQL挺好用的,但是终归没有与其他技术 相关联,只有NHibernate用到,一 ...

  5. NHibernate - ICriteria 查询

    http://blog.knowsky.com/213234.htm http://blog.chinaunix.net/uid-20463341-id-1673509.html http://www ...

  6. NHibernate 数据查询之Linq to NHibernate

    刚学NHibernate的时候觉得,HQL挺好用的,但是终归没有与其他技术相关联,只有NHibernate用到,一来容易忘记,二来没有智能提示,排除错误什么的都不给力,直到看到一个同事用Linq to ...

  7. NHibernate Linq查询 扩展增强 (第九篇)

    在上一篇的Linq to NHibernate的介绍当中,全部是namespace NHibernate命名空间中的IQueryOver<TRoot, TSubType>接口提供的.IQu ...

  8. 让OData和NHibernate结合进行动态查询

    OData是一个非常灵活的RESTful API,如果要做出强大的查询API,那么OData就强烈推荐了.http://www.odata.org/ OData的特点就是可以根据传入参数动态生成Ent ...

  9. [NHibernate]一对多关系(关联查询)

    目录 写在前面 文档与系列文章 一对多查询 总结 写在前面 上篇文章介绍了nhibernate的一对多关系如何配置,以及级联删除,级联添加数据的内容.这篇文章我们将学习nhibernate中的一对多关 ...

随机推荐

  1. 使用compareDocumentPosition比较两个元素在文档中的位置

    PS:尊重原创,转载请注明来自http://www.cnblogs.com/Raoh/p/js_compareDocumentPosition_between_two_node.html 使用comp ...

  2. SAP SOAMANAGER 配置WEBSERVICE 提示:Service cannot be reached解决方法

    TM中有些服务没有被激活,以UI界面个性化设置化设置为例: 如果服务没有被激活,打开界面就会显示: 这时候右键点击属性,获取服务ID: 通过事务代码SICF,输入服务ID:wd_analyze_con ...

  3. 在一个文件中有10G个整数,乱序排列,要求找出中位数

     题目:在一个文件中有 10G 个整数,乱序排列,要求找出中位数.内存限制为 2G.只写出思路即可(内存限制为 2G的意思就是,可以使用2G的空间来运行程序,而不考虑这台机器上的其他软件的占用内存). ...

  4. mysql 支持emoji

    1.修改my.cnf [client] default-character-set = utf8mb4 [mysqld] collation-server = utf8mb4_unicode_ci c ...

  5. AngularJS - 定时器 倒计时例子

    <body> <div ng-app="myApp"> <div ng-controller="firstController"& ...

  6. Debian下的PPPOE服务器配置

    参考: http://blog.csdn.net/zhangwenjianqin/article/details/7655375 http://blog.sina.com.cn/s/blog_8043 ...

  7. 中兴电信光纤猫F612管理员密码获取方法

    1.telnet 192.168.1.1 账号:root 密码:Zte521 2.输入命令: sendcmd 1 DB p DevAuthInfo 得到管理员账号密码如下: <DM name=& ...

  8. TIANKENG’s rice shop

    Problem Description TIANKENG managers a pan fried rice shop. There are n kinds of fried rice numbere ...

  9. iOS之内购

    很久之前就想出一篇IOS内付费的教程,但是一查网上的教程实在太多了,有的写得真的蛮不错的,就心想算了,于是就保存在草稿箱了.至于为什么写完它呢!真是说来话长,最近公司有个项目经理跑来问我有关苹果内付费 ...

  10. [改善Java代码]避开基本类型数组转换列表陷阱

    开发中经常用到Arrays和Collections这两个工具类. 在数组和列表之间进行切换.非常方便.但是也会遇到一些问题. 看代码: import java.util.Arrays; import ...