• Nhibernate系列学习之(三) Criteria查询表达式增删改查


    Criteria查询表达式:

      正如我们所见,Expression对查询语句的表达式进行了封装和限制,下表列出了Expression所有的方法,以及每个方法所对应的查询表达式及其限制。

    Restrictions的用法:

     

    方法

    说明

    Restrictions.eq

    Restrictions.allEq

    利用Map来进行多个等于的限制

    Restrictions.gt

    Restrictions.ge

    >=

    Restrictions.lt

    Restrictions.le

    <=

    Restrictions.between

    BETWEEN                                       

    Restrictions.like

    LIKE      eg:  Restrictions.Like("Inquirer", "%"+condition.Inquirer+"%")

    Restrictions.in

    in

    Restrictions.and

    and

    Restrictions.or

    or

    Restrictions.sqlRestriction

    用SQL限定查询

    方法描述

     

    注意:Expression各方法中的属性参数(各方法中的第一个参数)所指定的属性名称(如:name,sex),并不是数据库表中的实际字段名称,而是实体对象中映射实际数据表字段的类属性名称。

    NHibernate.ICriteria接口表示特定持久类的一个查询。ISession是 ICriteria实例的工厂。

     

    这里以Northwind数据库为示例数据库

    示例数据表:Employees

    现在只用雇员表中部分字段。

    持久类如下:

    public class Employees
    
        {
    
            public virtual int EmployeeID { get; set; }
    
            public virtual string LastName { get; set; }
    
            public virtual string FirstName { get; set; }
    
            public virtual DateTime BirthDate { get; set; }
    
            public virtual string Address { get; set; }
    
            public virtual string City { get; set; }
    
            public virtual string PostalCode { get; set; }
    
        }

     

    映射文件如下:

    <?xml version="1.0" encoding="utf-8" ?>
    
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Domain" namespace="Domain.Entities">
    
      <class name="Employees" table="Employees">
    
        <id name="EmployeeID" column="EmployeeID">
    
          <generator class="identity"></generator>
    
        </id>
    
        <property name="LastName" column="LastName" type="String"></property>
    
        <property name="FirstName" column="FirstName" type="String"></property>
    
        <property name="BirthDate" column="BirthDate" type="DateTime"></property>
    
        <property name="Address" column="Address" type="String"></property>
    
        <property name="City" column="City" type="String"></property>
    
        <property name="PostalCode" column="PostalCode" type="String"></property>
    
      </class>
    
    </hibernate-mapping>

    1、使用ISession对象的Get()方法来根据主键查询对象
       语法:T ISession.Get<T>(object Id)
       通常使用这种方法来根据主键Id值来查询对象的,并返回查询到的实体对象
      
    2、使用HQL语句来实现查询。
       为了实现对对象的灵活操作,NHibernate也引入了Hibernate查询语言(HQL,NHibernate Query Language),这种语句与SQL语句很像,但它是基于面向对象查询语言。它实际上是用OOP中的对象和属性映射了数据库中的表和列。
       例如这一句:select c.Firstname from Customer c
       Customer是一个对象,Firstname是Customer对象的属性。
       在这里主要讨论一下from子句,select子句,where子句,order by子句,group by子句几个常用的子句。
      
       from子句:
       如“from Fruit”:就是取出Fruit实体类所映射的表的所有记录。还可以加上别名“from Fruit as f”。

    public IList<Fruit> Select()
        {
            IList<Fruit> list = _Session.CreateQuery("from Fruit").List<Fruit>();
            return list;
        }

     
        这里返回的是Fruit实体对象的集合。

        select子句:
        用来指定要从实体类所对应的表中检索出哪些属性。

    public IList<object[]> SelectAll()
        {
            IList<object[]> list = _Session.CreateQuery("select f.Id,f.Name,f.Price from Fruit as f ").List<object[]>();
            return list;
        }


        由于只是查询了有限的列出来,所以返回的不是实体对象的集合,而是object[]数组的集合。只要在select子句中指定多列,就不能返回实体对象的集合,而是返回object[]的集合。
       
        另外需要注意的是:HQL语句中实体类的名子和属性的名子大小写敏感。
       
        下面的代码是只查询不重复的Stack属性值的集合,由于查询结果只有一列,所以返回一个字符串的集合就可以了。
       

    public IList<string> GetStacks()
        {
            IList<string> list = _Session.CreateQuery("select distinct f.Stack from Fruit as f").List<string>();
            return list;
        }

       
        where子句:
        用来从实体类对应的表中筛选出指定的对象集合。我们所知道的where中的and、or、not、is、like、between、in、>、<、=等等都可以直接拿来使用,
        如:
        select p.Name from Person p where p.Age > 20
        from Person p where p.Age between 20 and 30
        from person p where p.Age in (20,30)
        from person p where p.Name is null
        from person p where p.Name like 'Jaki%'
       
        那如何在where子句中使用参数呢?比如我们要做一个登录,需要根据用户名和密码查询,那我们的HQL语句应当使用变量参数,变量参数以":参数名"的形式表示
        from Login as login where login.Id=:u and login.Password=:p
        那我们如何给:u和:p赋值呢?我们可以使用IQuery的SetXXX()方法(SetString(),SetBoolean(),SetInt32()......)来为参数赋值
        下面是我们登录的代码段:

    public bool Select(string uid, string pwd)
        {
            //写法1
            //IList<Login> list = _Session.CreateQuery("from Login as login where login.Id='"+uid+"' and login.Password='"+pwd+"'").List<Login>();
            //写法2
            //IList<Login> list = _Session.CreateQuery("from Login as login where login.Id=? and login.Password=?").SetString(0,uid).SetString(1,pwd).List<Login>();
            //写法3
            IList<Login> list = _Session.CreateQuery("from Login as login where login.Id=:u and login.Password=:p").SetString("u",uid).SetString("p",pwd).List<Login>();
            return list.Count > 0 ? true : false;
        }


        书写HQL参数有四种写法:
        写法1:可能会引起SQL注入,不要使用。
        写法2:ADO.NET风格的参数,NHibernate的参数从0开始计数。
        写法3:命名参数用:name的形式在查询字符串中表示,这时IQuery接口把实际参数绑定到命名参数。
        写法4:命名的参数列表,把一些参数添加到一个集合列表中的形式,比如可以查询数据是否在这个集合列表

        order by子句与group by 子句与SQL语法很像,在此不多说了,代码如下。

        public IList<Customer> Orderby()
        {
            return _session.CreateQuery("select from Customer c order by c.Firstname asc,c.Lastname desc").List<Customer>();
        }
        public IList<object[]> Groupby()
        {
            return _session.CreateQuery("select c.Firstname, count(c.Firstname) from Customer c group by c.Firstname").List<object[]>();
        }

     

    一、开始

    (一) 返回所有实例(返回所有雇员)

    这里返回的所有实例,且是全部的属性(字段)

    ICriteria crt = _session.CreateCriteria(typeof(Employees));           
    
    return crt.List<Employees>();

    Isession创建条件查询实例有4个构造方法。

    (二)  返回部分实例(返回2个雇员)

    ICriteria crt = _session.CreateCriteria(typeof(Employees));
    
    crt.SetMaxResults(2);
    
    return crt.List<Employees>();

    (三)条件查询的约束条件

    (1)Expression

    ICriteria crt = _session.CreateCriteria(typeof(Employees));
    
    crt.Add(Expression.Eq("City","London"));
    
    return crt.List<Employees>();

    查询内容为:雇员的城市是在伦敦的。其中Expression的名字空间为:NHibernate.Criterion

    Expression类 定义了获得某些内置ICriterion类型的工厂方法,这里用到了等于

    (2)Restriction

    ICriteria crt = _session.CreateCriteria(typeof(Employees));
    
    crt.Add(Restrictions.Eq("City", "London"));
    
    return crt.List<Employees>();

     

    查询内容为:雇员的城市是在伦敦的。其中Restrictions的名字空间为:NHibernate.Criterion

    (3)通过实例来查询

    Employees ee = new Employees { City = "London", BirthDate = Convert.ToDateTime("1955-03-04 00:00:00.000") };
    
    ICriteria crt = _session.CreateCriteria(typeof(Employees));
    
    crt.Add(Example.Create(ee));
    
    return crt.List<Employees>();

    查询伦敦的,生日在那个时间的。(为什么这里我要加个生日上去?因为我的持久类中有这个属性,如果在实例查询中不给定这个值,会有日期越界的异常。在下边的例子中,来处理这种情况)这是限制的相等的实现。下边实现一个相似的例子:

    Employees ee = new Employees { FirstName = "a"};
    
    Example exp=Example.Create(ee).EnableLike(MatchMode.Start).ExcludeProperty("BirthDate").IgnoreCase();
    
    ICriteria crt = _session.CreateCriteria(typeof(Employees));
    
    crt.Add(exp);
    
    return crt.List<Employees>();

    这个例子中,指定相似的姓名等a,看实例exp:

    ·采用相似比较EnableLike

    ·相似比较匹配模式MatchMode.Start,开头匹配,这个应该类似于SQL中的a%

    ·排除比较属性ExcludeProperty,这个方法就是用于处理排除的。上个例子中日期没给,所以会出现异常,而这个方法则排除了这种异常发生(其实就是排除不比较的属性(字段))。

    ·忽略大小写

    (四)排序

    ICriteria crt = _session.CreateCriteria(typeof(Employees));
    
    crt.AddOrder(new NHibernate.Criterion.Order("FirstName", true));
    
    return crt.List<Employees>();

    排序字段:名字,升序(true)

    (五)聚合

    (1)查询人数

    ICriteria crt = _session.CreateCriteria(typeof(Employees));
    
    crt.SetProjection(Projections.RowCount());
    
    return crt.List();

    NHibernate.Expression.Projections是 IProjection 的实例工厂。通过调用 SetProjection()应用投影到一个查询。

    (2)Avg

    从这个开始到以下的例子又回到以Products为示例数据表

    ICriteria crt = _session.CreateCriteria(typeof(Products));           
    
    crt.SetProjection(Projections.ProjectionList().Add(Projections.Avg("Price")));
    
    return crt.List();

    通过投影列表来添加投影聚合方法。

    这里取得产品的平均价格,这里没有条件约束,下边这个例子取得产品类别为2的产品的平均价格:

    ICriteria crt = _session.CreateCriteria(typeof(Products));           
    
    crt.SetProjection(Projections.ProjectionList().Add(Projections.Avg("Price"))).Add(Expression.Eq("CategoryID",2));
    
    return crt.List();

    (3)Max(最大价格)

    ICriteria crt = _session.CreateCriteria(typeof(Products));
    
    crt.SetProjection(Projections.ProjectionList().Add(Projections.Max("Price")));
    
    return crt.List();

    (4)Min(最低价格)

    ICriteria crt = _session.CreateCriteria(typeof(Products));
    
    crt.SetProjection(Projections.ProjectionList() .Add(Projections.Min ("Price")));
    
    return crt.List();

    (5)Sum(和)

    ICriteria crt = _session.CreateCriteria(typeof(Products));
    
    crt.SetProjection(Projections.ProjectionList().Add(Projections.Sum ("Price")));
    
    return crt.List();

    (6)分组

    ICriteria crt = _session.CreateCriteria(typeof(Products));
    
    crt.SetProjection(Projections.ProjectionList().Add(Projections.GroupProperty("CategoryID")));
    
    return crt.List<int>();

    这个分组只是返回一个属性,所以用int泛型可以了。下边的例子返回分组,并返回各组的数目

    ICriteria crt = _session.CreateCriteria(typeof(Products));
    
    crt.SetProjection(Projections.ProjectionList().Add(Projections.GroupProperty("CategoryID")).Add(Projections.RowCount()));
    
    return crt.List();

    这里的List为System.Collections.Ilist,且是object[]类型的

    二、向数据库新增记录
        1.新建对象;
        2.调用ISession.Save();
        3.调用Flush()同步到数据库。

        public void Insert(Fruit fruit)
        {
            _Session.Save(fruit);
            _Session.Flush();
        }

       
    三、修改记录
        1.获取对象;
        2.修改它的一些属性;
        3.调用ISession.Update();
        4.调用Flush同步到数据库。

        public void Update(Fruit fruit)
        {
            _Session.Update(fruit);
            _Session.Flush();
        }

     
    四、删除记录
    1.获取要删除的对象;
    2.调用ISession.Delete();
    3.调用Flush同步到数据库。

        public void Delete(Fruit fruit)
        {
            _Session.Delete(fruit);
            _Session.Flush();
        }

     


  • 相关阅读:
    【Git】常规操作指令
    SourceTree Push 代码报错:remote: Support for password authentication was removed on April 26, 2022.
    【Vue】事件修饰符
    leetcode 周赛290
    如何通过接口工具,和复制浏览器的请求参数,来模拟调式接口
    Unreal 输入系统 解析
    Poco API精讲之 等待 wait
    Poco API精讲之点击click()、long_click()、double_click()
    Airtest的前世今生
    2022年最新版本QT安装教程
  • 原文地址:https://www.cnblogs.com/jiangshuai52511/p/7237977.html
Copyright © 2020-2023  润新知