NHibernate系列文章二十六:NHibernate查詢之SQL Query查詢(附程序下載)


摘要

NHibernate在很早的版本就提供了SQL Query(原生SQL查詢),對於很復雜的查詢,如果使用其他的查詢方式實現比較困難的時候,一般使用SQL Query。使用SQL Query是基於原生的SQL語句,查詢后將結果做投影到NHibernate實體類對象的過程。也可以投影到其他任何.net集合類。

本篇文章的代碼可以到NHibernate查詢下載

1、from子句

1         public IList<Customer> GetAllSQL()
2         {
3             return Session.CreateSQLQuery("select * from Customer").AddEntity(typeof(Customer)).List<Customer>();
4         }

首先創建調用ISession.CreateSQLQuery方法,傳入原生的SQL語句,生成ISQLQuery對象,這是使用SQL Query的第一步。

ISQLQuery.AddEntity方法傳入類型參數,將查詢結果映射到Customer類。

ISQLQuery.List方法立即執行,返回查詢結果。

2、as子句提供別名,as可以省略

1         public IList<Customer> GetAllSQL()
2         {
3             return Session.CreateSQLQuery("select * from Customer as c").AddEntity(typeof(Customer)).List<Customer>();
4         }

3、指定列返回數組

1         public IList<int> SelectIdSQL()
2         {
3             return Session.CreateSQLQuery("select distinct c.Id from Customer c")
4                 .AddScalar("Id", NHibernateUtil.Int32) 5                 .List<int>();
6         }

ISQLQuery.AddScalar方法將查詢語句的列映射到.net數據類型,傳入的第一個參數是列名,第二個參數是類型,NHibernateUtil類中的公開了很多靜態實例對象表示映射數據類型,這里使用Int32。

4、where子句

 1         public IList<Customer> GetCustomerByNameSQL(string firstName, string lastName)
 2         {
 3             return Session.CreateSQLQuery("select * from Customer where FirstName = :firstName and LastName = :lastName")
 4                 .AddEntity(typeof(Customer))
 5                 .SetString("firstName", firstName)
 6                 .SetString("lastName", lastName)
 7                 .List<Customer>();
 8         }
 9 
10         public IList<Customer> GetCustomersStartWithSQL()
11         {
12             return Session.CreateSQLQuery("select * from Customer where FirstName like 'J%'")
13                 .AddEntity(typeof(Customer))
14                 .List<Customer>();
15         }

SQL Query的查詢參數傳遞跟HQL參數傳遞是一樣的。而且這里是使用原生的SQL語句,比HQL更方便。

5、order by子句

1         public IList<Customer> GetCustomersOrderBySQL()
2         {
3             return Session.CreateSQLQuery("select * from Customer c order by c.FirstName")
4                 .AddEntity(typeof(Customer))
5                 .List<Customer>();
6         }

6、關聯查詢

 1      /// <summary>
 2         /// 按分組查詢客戶Id及客戶關聯的訂單數量
 3         /// </summary>
 4         /// <returns></returns>
 5         public IList<object[]> SelectOrderCountSQL()
 6         {
 7             return Session.CreateSQLQuery("select c.Id, count(*) as OrderCount from Customer c inner join [Order] o on c.Id=o.CustomerId group by c.Id")
 8                 .AddScalar("Id", NHibernateUtil.Int32)
 9                 .AddScalar("OrderCount", NHibernateUtil.Int32)
10                 .List<object[]>();
11         }
12 
13         /// <summary>
14         /// 查詢所有訂單數量大於2的客戶信息
15         /// </summary>
16         /// <returns></returns>
17         public IList<Customer> GetCustomersOrderCountGreaterThanSQL()
18         {
19             string sql = @"select * from Customer
20 where Id in
21 (
22     select c.Id from Customer c inner join [Order] o on c.Id = o.CustomerId
23     group by c.Id
24     having count(*) > 2
25 )";
26             return Session.CreateSQLQuery(sql)
27                 .AddEntity(typeof(Customer))
28                 .List<Customer>();
29         }
30 
31         /// <summary>
32         /// 查詢在指定日期到當前時間內有下訂單的客戶信息
33         /// </summary>
34         /// <param name="orderDate"></param>
35         /// <returns></returns>
36         public IList<Customer> GetCustomersOrderDateGreatThanSQL(DateTime orderDate)
37         {
38             return Session.CreateSQLQuery("select distinct c.* from Customer c inner join [Order] o on c.Id=o.CustomerId where o.Ordered > :orderDate")
39                 .AddEntity(typeof(Customer))
40                 .SetDateTime("orderDate", orderDate)
41                 .List<Customer>();
42         }

注意這幾個方法都是傳入的原生SQL語句,不管多復雜的查詢,只要會寫SQL語句,就能夠使用SQL Query返回對象集合。

如果是多個表的聯合查詢,返回結果的字段來自不同的表,這種情況我一般是使用Hashtable映射。使用SetResultTransformer(Transformers.AliasToEntityMap)將結果映射成EntityMap,然后調用List<Hashtable>()方法返回查詢結果,查詢方法返回的結果類型是IList<Hashtable>。

ISQLQuery.SetResultTransformer(Transformers.AliasToEntityMap)

 

結語

對於復雜的多表聯合查詢,以及復雜的分組查詢,應該使用SQL Query,因為使用它更方便,而且不容易出錯。雖然在效率上,比使用其他的方式要略低。但是前提是項目只打算用SQL Server數據庫或只用Oracle數據庫,因為是使用的原生SQL語句,而SQL Server數據庫和Oracle數據庫在寫查詢的時候還是有很多語法上的差別。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM