01-04-03【Nhibernate (版本3.3.1.4000) 出入江湖】Criteria API关联查询

Criteria API关联查询

    如果说HQL查询还有需要了解点SQL语法知识,并不是完全彻底面向对象查询,

   那么Criterial API就是完全面向对象的查询方式。

 

1 public IList<Customer> UseCriteriaAPI_GetCustomersWithOrders(DateTime orderDate)
2 {
3     return _session.CreateCriteria(typeof(Customer))
.Add(Restrictions.Eq("FirstName", "easy5")) //为本表查询添加查询参数
4 .CreateCriteria("Orders") //关联查询Order表开始,注意:“Oreders”是类Customer中关联到Order类的属性
.Add(Restrictions.Gt("OrderDate", orderDate))//OrderDate是Order类中的属性,不是数据库表Order的列名,如果是列名就不是面向对象编程了

.List<Customer>();
 }

我们使用CreateCriteria()在关联之间导航,很容易地在实体之间指定约束。

这里第二个CreateCriteria()返回一个ICriteria的新实例,并指向Orders实体的元素。

在查询中子对象使用子CreateCriteria语句,这是因为实体之间的关联我们在映射文件中已经定义好了。

还有一种方法使用CreateAlias()不会创建ICriteria的新实例。

预过滤

使用ICriteria接口的SetResultTransformer(IResultTransformer resultTransformer)方法返回满足特定条件的Customer。上面例子中使用条件查询,观察其生成的SQL语句并没有distinct,这时可以使用NHibernate.Transform命名空间中的方法或者使用NHibernate提供的NHibernate.CriteriaUtil.RootEntity、NHibernate.CriteriaUtil.DistinctRootEntity、NHibernate.CriteriaUtil.AliasToEntityMap静态方法实现预过滤的作用。那么上面的查询应该修改为:

public IList<Customer> UseCriteriaAPI_GetCustomersWithOrders(DateTime orderDate)
{
    return _session.CreateCriteria(typeof(Customer))
        .CreateCriteria("Orders")
        .Add(Restrictions.Gt("OrderDate", orderDate))
        .SetResultTransformer(new NHibernate.Transform.DistinctRootEntityResultTransformer()) //过滤重复项
        .List<Customer>();
}

这个例子从转换结果集的角度实现了我们想要的效果。

投影

调用SetProjection()方法可以实现应用投影到一个查询中。NHibernate.Criterion.Projections是Projection的实例工厂,Projections提供了非常多的方法,看看下面的截图

 

现在可以条件查询提供的投影来完成上面同样的目的:

public IList<Customer> UseCriteriaAPI_GetDistinctCustomers(DateTime orderDate)

{

    IList<int> ids = _session.CreateCriteria(typeof(Customer))

        .SetProjection(Projections.Distinct(Projections.ProjectionList()

                                                          .Add(Projections.Property("CustomerId"))

                                                      )

                           )

        .CreateCriteria("Orders")

        .Add(Restrictions.Gt("OrderDate", orderDate))

        .List<int>();

 

    return _session.CreateCriteria(typeof(Customer))

        .Add(Restrictions.In("CustomerId", ids.ToArray<int>()))

        .List<Customer>();

}

我们可以添加若干的投影到投影列表中,例如这个例子我添加一个CustomerId属性值到投影列表中,这个列表中的所有属性值都设置了Distinct投影,第一句返回订单时间在orderDate之后所有顾客Distinct的CustomerId,第二句根据返回的CustomerId查询顾客列表。达到上面的目的。这时发现其生成的SQL语句中有distinct。我们使用投影可以很容易的组合我们需要的各种方法。

范例:

 1  #region CriterialAPI 查询
 2 
 3         public IList<Customer> GetEntitysByDateTimeCriterialApi(DateTime dateTime)
 4         {
 5             IList<Customer> result = null;
 6             ISession session = _sessionManager.GetSession();
 7 
 8             result = session.CreateCriteria(typeof(Customer))
 9                 .CreateCriteria("Orders")
10                 .Add(Restrictions.Gt("OrderDate", dateTime))
11                 .List<Customer>();
12             
13             return result;
14         }
15 
16 
17         /// <summary>
18         /// 利用CreiteriaAPI进行的IN关键字的查询测试
19         /// </summary>
20         public IList<Customer> UseCreiteriaAPI_IN_Query()
21         {
22             ISession session = _sessionManager.GetSession();
23             // return session.CreateCriteria(typeof(Customer)).CreateCriteria("Orders").Add(Restrictions.Between("OrderDate", startDate, endDate))
24             // .List<Customer>();
25 
26             object[] firstnames = { "zhang", "li" };
27             return session.CreateCriteria(typeof(Customer))
28                 .Add(Restrictions.In("FirstName", firstnames))
29                 .List<Customer>();
30 
31             //return null;
32         }
33 
34         /// <summary>
35         /// 利用CreiteriaAPI进行的Or关键字的查询测试
36         /// </summary>
37         public IList<Customer> UseCreiteriaAPI_Or_Query()
38         {
39             ISession session = _sessionManager.GetSession();
40             String[] firstnames = { "zhang", "li" };
41             return session.CreateCriteria(typeof(Customer))
42                 .Add(Restrictions.Or(Restrictions.Eq("FirstName", "zhang"), Restrictions.Eq("FirstName", "li")))
43                 .List<Customer>();
44         }
45 
46         //CriteriaAPI的预过滤测试
47         public IList<Customer> UseCriteriaAPI_GetCustomersWithOrders(DateTime orderDate)
48         {
49             ISession session = _sessionManager.GetSession();
50 
51             return session.CreateCriteria(typeof(Customer))
52                 .CreateCriteria("Orders")
53                 .Add(Restrictions.Gt("OrderDate", orderDate))
54                 .SetResultTransformer(new NHibernate.Transform.DistinctRootEntityResultTransformer()) //Distinct--过滤重复项
55                 
56                 .List<Customer>();
57         }
58 
59         //CriteriaAPI的Projection投影测试
60         public IList<Customer> UseCriteriaAPI_GetDistinctCustomers(DateTime orderDate)
61         {
62             ISession session = _sessionManager.GetSession();
63 
64             IList<int> ids = session.CreateCriteria(typeof(Customer))
65                 .SetProjection(Projections.Distinct(Projections.ProjectionList().Add(Projections.Property("CustomerId"))
66                 ))
67                 .CreateCriteria("Orders")
68                 .Add(Restrictions.Gt("OrderDate", orderDate))
69                 .List<int>();
70 
71 
72             return session.CreateCriteria(typeof(Customer))
73                 .Add(Restrictions.In("CustomerId", ids.ToArray<int>()))
74                 .List<Customer>();
75         }
76 
77         //CriteriaAPI的Projection投影测试
78         public IList<Object[]> UseCriteriaAPI_GetDistinctCustomers2()
79         {
80             ISession session = _sessionManager.GetSession();
81 
82             return session.CreateCriteria(typeof(Customer))
83                 .SetProjection(Projections.ProjectionList()
84                 .Add(Projections.Property("FirstName")).Add(Projections.Property("LastName")))
85                 .List<Object[]>();
86 
87 
88         }
89 
90         #endregion

 动态查询---关联查询:

 1         public IList<Customer> UseCriteriaApiAdvQuery(String firstName,
 2             String lastName,
 3             DateTime dateTime)
 4         {
 5             ICriteria criteria = _session.CreateCriteria("Customer");
 6             if (null != firstName)
 7             {
 8                 criteria.Add(Restrictions.Eq("FirstName", firstName)); 
 9             }
10             if (null != lastName)
11             {
12                 criteria.Add(Restrictions.Eq("LastName", lastName)); 
13             }
14 
15             if (null != dateTime)
16             {
17                 //关联查询Order
18                 // 注意:不是criteria.CreateCriteria("Order"),如果是,会抛异常:
19                 //{"could not resolve property: Order of: Model.Customer"}
20                 //而是criteria.CreateCriteria("Orders"),Orders是Customer类在关联的Order类的属性
21                 criteria.CreateCriteria("Orders").Add(Restrictions.Eq("OrderDate", dateTime)); 
22             }
23 
24             return criteria.List<Customer>();
25         }
26 
27 测试代码:
28 
29         [TestMethod]
30         public void TestUseCriteriaApiADvQuery()
31         {
32             CustomerService customerService = new CustomerService();
33             OrderService orderService = new OrderService();
34 
35             Customer customer = new Customer()
36             {
37                 FirstName = "Test",
38                 LastName = "TestUseCriteriaApiADvQuery",
39                 Age = 111
40             };
41 
42             Order order1 = new Order()
43             {
44                 OrderDate = DateTime.Now,
45                 Customer = customer
46             };
47 
48             customer.Orders.Add(order1);
49             customerService.Add(customer);
50 
51             Assert.IsNotNull(customerService.Find(customer.CustomerId));
52             Assert.IsNotNull(orderService.Find(order1.OrderId));
53 
54 
55             IList<Customer> customers =
56                 customerService.UseCriteriaApiAdvQuery(customer.FirstName,
57                 customer.LastName, order1.OrderDate);
58 
59             Assert.IsTrue(customers.Count > 0);
60         }
View Code

动态查询---模糊查询:

        #region CriterialAPI 动态+模糊查询

        public IList<Customer> UseCriteriaApiLikeQuery(String firstName,
            String lastName)
        {
            ICriteria criteria = _session.CreateCriteria("Customer");
            if (null != firstName)
            {
                //方式一:用原生的匹配字符,如:%
                criteria.Add(Restrictions.Like("FirstName", "%" + firstName +"%"));
            }
            if (null != lastName)
            {
                //方式二:用MatchMode
                criteria.Add(Restrictions.Like("LastName", lastName, MatchMode.Anywhere));
            }

            return criteria.List<Customer>();
        }

        #endregion

测试代码:

        #region 测试CriteriaAPI查询--动态 + 模糊查询

        [TestMethod]
        public void TestUseCriteriaApiLikeQuery()
        {
            CustomerService customerService = new CustomerService();
            OrderService orderService = new OrderService();

            Customer customer = new Customer()
            {
                FirstName = "Test",
                LastName = "TestUseCriteriaApiLikeQuery",
                Age = 111
            };

            Order order1 = new Order()
            {
                OrderDate = DateTime.Now,
                Customer = customer
            };

            customer.Orders.Add(order1);
            customerService.Add(customer);

            Assert.IsNotNull(customerService.Find(customer.CustomerId));
            Assert.IsNotNull(orderService.Find(order1.OrderId));

            IList<Customer> customers =
                customerService.UseCriteriaApiLikeQuery(null,
                "CriteriaApiLike");

            Assert.IsTrue(customers.Count > 0);
        }

        #endregion

 排序:

        /// <summary>
        /// 模糊查询+排序
        /// </summary>
        /// <param name="firstName"></param>
        /// <param name="lastName"></param>
        /// <returns></returns>
        public IList<Customer> UseCriteriaApiLikeQueryAndDescOrder(String firstName,
            String lastName)
        {
            ICriteria criteria = _session.CreateCriteria("Customer");
            if (null != firstName)
            {
                //方式一:用原生的匹配字符,如:%
                criteria.Add(Restrictions.Like("FirstName", "%" + firstName +"%"));
            }
            if (null != lastName)
            {
                //方式二:用MatchMode
                criteria.Add(Restrictions.Like("LastName", lastName, MatchMode.Anywhere))
                        .AddOrder(NHibernate.Criterion.Order.Desc("CustomerId"));
            }

            return criteria.List<Customer>();
        }

        #endregion

测试代码:

        [TestMethod]
        public void TestUseCriteriaApiLikeQueryAndDescOrder()
        {
            CustomerService customerService = new CustomerService();
            OrderService orderService = new OrderService();

            Customer customer1 = new Customer()
            {
                FirstName = "Test",
                LastName = "TestUseCriteriaApiLikeQuery1",
                Age = 111
            };

            Customer customer2 = new Customer()
            {
                FirstName = "Test",
                LastName = "TestUseCriteriaApiLikeQuery2",
                Age = 111
            };

            customerService.Add(customer1);
            customerService.Add(customer2);
            Assert.IsNotNull(customerService.Find(customer1.CustomerId));
            Assert.IsNotNull(customerService.Find(customer2.CustomerId));

            IList<Customer> customers =
                customerService.UseCriteriaApiLikeQueryAndDescOrder(null, "CriteriaApiLike");

            Assert.IsTrue(customer1.CustomerId < customer2.CustomerId);
            Assert.IsTrue(customers[0].LastName== customer2.LastName);
        }
View Code
原文地址:https://www.cnblogs.com/easy5weikai/p/3749044.html