• NHibernate系列文章二十三:NHibernate查询之Criteria查询(附程序下载)


    摘要

    上一篇文章介绍了NHibernate HQL,他的缺点是不能够在编译时发现问题。如果数据库表结构有改动引起了实体关系映射的类有改动,要同时修改这些HQL字符串。这篇文章介绍NHibernate面向对象的Criteria查询。他提供了很多API接口,可以实现“私人订制”式的面向对象查询。

    作为对照,本篇文章将上篇文章的八个HQL查询全部用Criteria查询写一遍,读者可以自己感受下他们之间的区别。

    本篇文章的代码可以到NHibernate查询下载

    1、创建Criteria对象,查询所有Customer对象信息

    1         public IList<Customer> QueryAllCriteria()
    2         {
    3             return Session.CreateCriteria<Customer>().List<Customer>();
    4         }

    ISession.CreateCriteria方法返回持久化查询对象的ICriteria实例,他是使用Criteria查询的第一步。传入一个类型参数,表示是对哪一个实体类持久化对象的查询实例。List方法返回持久化类的所有对象。

    2、CreateAlias方法创建别名

    1         public IList<Customer> QueryAllCriteria()
    2         {
    3             return Session.CreateCriteria<Customer>()
    4                 .CreateAlias("Customer", "c").List<Customer>();
    5         }

    3、指定对象返回数组

    1         public IList<int> SelectIdCriteria()
    2         {
    3             IList<int> ids = Session.CreateCriteria(typeof(Customer))
    4                                 .SetProjection(Projections.Distinct(Projections.ProjectionList().Add(Projections.Property("Id"))))
    5                                 .List<int>();
    6             return ids;
    7         }

    ICriteria.SetProjection方法将应用投影到查询中,Projections有很多静态方法生成Distinct、GroupBy、Max、Min、Avg、Sum等投影。

    4、添加查询条件

     1         public IList<Customer> GetCustomerByNameCriteria(string firstName, string lastName)
     2         {
     3             return Session.CreateCriteria<Customer>()
     4                 .Add(Restrictions.And(
     5                             Restrictions.Eq("FirstName", firstName), Restrictions.Eq("LastName", lastName))
     6                         ).List<Customer>();
     7         }
     8 
     9         public IList<Customer> GetCustomersStartWithCriteria()
    10         {
    11             var list = Session.CreateCriteria<Customer>().Add(Restrictions.Like("FirstName", "J%")).List<Customer>();
    12             return list.ToList();
    13         }

    ICriteria.Add方法用来添加where条件,Restrictions类提供了很多生成查询条件的API方法。

    Restrictions.And方法和Restrictions.Or方法对应SQL的and和or条件,可以传入多个条件对象拼接and/or子句,可以灵活地使用括号进行分组。

    示例中的Restrictions.Eq方法和Restrictions.Like方法是最常用的Restrictions方法API。

    此外,Restrictions还提供Between、Ge、Gt、Le、Lt、In、IsNotNull、IsNull、Where等多个API方法,可以满足生成大部分查询条件。

    5、order by

    1         public IList<Customer> GetCustomersOrderByCriteria()
    2         {
    3             var list = Session.CreateCriteria<Customer>().AddOrder(new NHibernate.Criterion.Order("FirstName", true)).List<Customer>();
    4             return list.ToList();
    5         }

    ICriteria.AddOrder方法添加order子句,传入Criteria.Order对象。Criteria.Order类构造函数传入两个参数,第一个参数表示对哪个属性进行排序,第二个字段表示是升序还是降序,true是升序,false是降序。

    6、关联查询

    1)按分组查询客户Id及客户关联的订单数量

     1         public IList<object[]> SelectOrderCountCriteria()
     2         {
     3             var query = Session.CreateCriteria(typeof(Customer)).CreateCriteria("Orders")
     4                     .SetProjection(Projections.ProjectionList()
     5                     .Add(Projections.GroupProperty("Id"))
     6                     .Add(Projections.RowCount()));
     7             return query.List<object[]>();
     8         }

    对查询进行分组通用的代码是:

                var query = Session.CreateCriteria(typeof(类名))
                                .SetProjection(Projections.ProjectionList()
                                .Add(Projections.GroupProperty("属性名"))
                                .Add(Projections.RowCount() | Projections.Max("Max投影属性名") | Projections.Sum("Sum投影属性名")));

    因为要对Order记录进行分组统计,所以使用CreateCriteria("Orders")创建与Orders的关联。

    2)查询在指定日期到当前内所有下订单客户信息

    1         public IList<Customer> GetCustomersOrderDateGreatThanCriteria(DateTime orderDate)
    2         {
    3             return Session.CreateCriteria<Customer>().CreateCriteria("Orders").Add(Restrictions.Gt("Ordered", orderDate))
    4                 .SetResultTransformer(new NHibernate.Transform.DistinctRootEntityResultTransformer())
    5                 .List<Customer>();
    6         }

    ICriteria.SetResultTransformer(new NHibernate.Transform.DistinctRootEntityResultTransformer())的结果相当于对HQL查询使用了distinct子句。

    3)查询所有订单数量大于2的客户信息

     1         public IList<Customer> GetCustomersOrderCountGreaterThanCriteria()
     2         {
     3             var query = Session.CreateCriteria(typeof(Customer)).CreateCriteria("Orders")
     4                             .SetProjection(Projections.ProjectionList()
     5                             .Add(Projections.GroupProperty("Id"))
     6                             .Add(Projections.RowCount()));
     7             IList<object[]> groups = query.List<object[]>();
     8 
     9             IList<int> ids = groups.Where(g => (int)g[1] > 2).Select(g => (int)g[0]).ToList();
    10 
    11             return Session.CreateCriteria(typeof(Customer))
    12                        .Add(Restrictions.In("Id", ids.ToArray<int>()))
    13                        .List<Customer>();
    14         }

    因为ICriteria目前不支持对Group分组结果进行Having筛选,因此必须先对Customer和Orders的关联查询以Customer.Id进行分组,得到Customer.Id和Order数量作为属性的对象的集合,对这个集合执行linq查询,得到订单数量大于2的客户Id集合,最后用Restrictions.In方法对Customer对象集合进行筛选,选出Customer.Id在订单数量大于2的客户Id集合内的客户信息。这样就能够实现Having的查询功能。

    结语

    NHibernate Criteria查询优点是完全面向对象,ICriteria对象提供了大量的API函数实现完全面向对象的查询语句。可以在编译时发现问题。在更改实体类属性后(如果改动不大),不怎么需要修改查询语句。缺点是功能有限,写复杂的分组查询和条件查询比较困难。一般情况下,在写简单查询的时候用Criteria查询,在写复杂查询的时候使用HQL或者Linq to NHibernate。

  • 相关阅读:
    python的参数传递
    django的objects级别的权限控制
    django如何将mysql数据库转化为model
    django的orm查询使用in的保序
    多用户OFDM系统资源分配研究
    第一代到第四代多址技术:从FDMA、TDMA、CDMA到OFDMA
    Kaggle比赛总结
    4 二维数组中的查找 JavaScript
    5 替换空格 JavaScript
    简单的HTTP协议
  • 原文地址:https://www.cnblogs.com/uncle_danny/p/5676049.html
Copyright © 2020-2023  润新知