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. ios开发——实用技术篇Swift篇&加速计和陀螺仪

    加速计和陀螺仪 //返回按钮事件 @IBAction func backButtonClick() { self.navigationController?.popViewControllerAnim ...

  2. grunt自动化工具

    Grunt和 Grunt 插件是通过 npm 安装并管理的,npm是 Node.js 的包管理器. 安装 CLI 首先,需要先将Grunt命令行(CLI)安装到全局环境中. npm install - ...

  3. Linux环境变量的修改(永久,暂时)

    Linux修改环境变量,很简单但很重要 一.Linux的变量种类 按变量的生存周期来划分,Linux变量可分为两类: 1. 永久的:需要修改配置文件,变量永久生效. 2. 临时的:使用export命令 ...

  4. 琐碎-关于hadoop2.X那些端口

    此文转载http://www.aboutyun.com/thread-7513-1-1.html Hadoop集群的各部分一般都会使用到多个端口,有些是daemon之间进行交互之用,有些是用于RPC访 ...

  5. 全面谈谈Aspects和JSPatch兼容问题

    1. 背景 Aspects 和 JSPatch 是 iOS 开发中非常常见的两个库.Aspects 提供了方便简单的方法进行面向切片编程(AOP),JSPatch可以让你用 JavaScript 书写 ...

  6. Hill Climber and Random Walk

  7. JavaScript版几种常见排序算法

    今天发现一篇文章讲“JavaScript版几种常见排序算法”,看着不错,推荐一下原文:http://www.w3cfuns.com/blog-5456021-5404137.html 算法描述: * ...

  8. 关于php一些数组函数

    array_column($array,"key") 将二维数组中的键名为key的数据生成一个新数组 array_unique($array) 去除重复值

  9. win10 IIS10 HTTP 错误 404.2 - Not Found

    环境win10系统IIS10里边发布web应用程序的时候,出现 HTTP 错误 404.2 - Not Found 由于 Web 服务器上的“ISAPI 和 CGI 限制”列表设置,无法提供您请求的页 ...

  10. [设计模式]<<设计模式之禅>>之关于单一职责原则

    单一职责原则的英文名称是Single Responsibility Principle,简称是SRP. 这个原则存在争议之处在哪里呢?就是对职责的定义,什么是类的职责,以及怎么划分类的职责.我们先举个 ...