- NHibernate 教程
- NHibernate - 首頁
- NHibernate - 概述
- NHibernate - 架構
- NHibernate - ORM
- NHibernate - 環境設定
- NHibernate - 入門
- NHibernate - 基礎 ORM
- NHibernate - 基礎 CRUD 操作
- NHibernate - Profiler
- 為對映檔案新增 IntelliSense
- NHibernate - 資料型別對映
- NHibernate - 配置
- NHibernate - 覆蓋配置
- NHibernate - 批處理大小
- NHibernate - 快取
- NHibernate - 對映元件
- NHibernate - 關係
- NHibernate - 集合對映
- NHibernate - 級聯操作
- NHibernate - 延遲載入
- NHibernate - 反向關係
- NHibernate - Load/Get
- NHibernate - LINQ
- NHibernate - 查詢語言 (HQL)
- NHibernate - Criteria 查詢
- NHibernate - QueryOver 查詢
- NHibernate - 原生 SQL
- NHibernate - Fluent NHibernate
- NHibernate 有用資源
- NHibernate - 快速指南
- NHibernate - 有用資源
- NHibernate - 討論
NHibernate - QueryOver 查詢
本章將介紹 QueryOver 查詢。這是一種新的語法,更類似於使用方法鏈語法的 LINQ,如下面的查詢所示。
var customers = session.QueryOver<Customer>() .Where(x => x.FirstName == "Laverne");
它在底層仍然是 Criteria,但是現在我們的查詢是強型別的。
正如我們在 Criteria 查詢中看到的,名字只是一個不透明的字串,現在我們實際上使用的是 **x.FirstName**,因此名字的重構和重新命名會在使用 QueryOver 的類似 LINQ 風格的 Criteria 查詢中發生更改。
我們仍然可以做許多類似的事情,但是你不能在 QueryOver 中使用查詢表示式語法,你必須使用方法鏈語法,並且你不能混合和匹配 LINQ 和 Criteria。
對於許多查詢,QueryOver API 非常有用,並且比直接使用 Criteria 提供更容易理解的物件語法。
讓我們來看一個簡單的例子,我們將使用 QueryOver 獲取名為 Laverne 的客戶。
using System;
using System.Data;
using System.Linq;
using System.Reflection;
using HibernatingRhinos.Profiler.Appender.NHibernate;
using NHibernate.Cfg;
using NHibernate.Criterion;
using NHibernate.Dialect;
using NHibernate.Driver;
using NHibernate.Linq;
namespace NHibernateDemo {
internal class Program {
private static void Main() {
var cfg = ConfigureNHibernate();
var sessionFactory = cfg.BuildSessionFactory();
using(var session = sessionFactory.OpenSession())
using(var tx = session.BeginTransaction()) {
var customers = session.QueryOver<Customer>()
.Where(x => x.FirstName == "Laverne");
foreach (var customer in customers.List()) {
Console.WriteLine(customer);
}
tx.Commit();
}
Console.WriteLine("Press <ENTER> to exit...");
Console.ReadLine();
}
private static Configuration ConfigureNHibernate() {
NHibernateProfiler.Initialize();
var cfg = new Configuration();
cfg.DataBaseIntegration(x => {
x.ConnectionStringName = "default";
x.Driver<SqlClientDriver>();
x.Dialect<MsSql2008Dialect>();
x.IsolationLevel = IsolationLevel.RepeatableRead;
x.Timeout = 10;
x.BatchSize = 10;
});
cfg.SessionFactory().GenerateStatistics();
cfg.AddAssembly(Assembly.GetExecutingAssembly());
return cfg;
}
}
}
正如你所看到的,它在底層仍然是 Criteria,但這只是一個更好的語法。
編譯並執行上述程式碼後,你將看到以下輸出。
Laverne Hegmann (4e97c816-6bce-11e1-b095-6cf049ee52be)
Points: 74
HasGoldStatus: True
MemberSince: 4/4/2009 12:00:00 AM (Utc)
CreditRating: Neutral
AverageRating: 0
Orders:
Order Id: 4ea14d96-6bce-11e1-b095-6cf049ee52be
Order Id: 4ea14d96-6bce-11e1-b096-6cf049ee52be
Order Id: 4ea14d96-6bce-11e1-b097-6cf049ee52be
Order Id: 4ea14d96-6bce-11e1-b098-6cf049ee52be
Press <ENTER> to exit...
其中一個缺點是,假設我們想說 **FirstName.StartsWith("A")**,如下面的程式所示。
var customers = session.QueryOver<Customer>() .Where(x => x.FirstName.StartsWith("A"));
foreach (var customer in customers.List()) {
Console.WriteLine(customer);
}
tx.Commit();
現在讓我們再次執行應用程式,你將看到這不是一個 LINQ 提供程式,因為它不知道這個 **StartsWith** 方法是什麼,因此你將得到一個 **執行時異常**。
異常提示未識別的呼叫方法。在這裡我們正在做顯而易見的事情,但這並不一定有效。
讓我們嘗試其他方法,例如 FirstName 等於“A%”,如下面的程式碼所示。
var customers = session.QueryOver<Customer>() .Where(x => x.FirstName == "A%");
foreach (var customer in customers.List()) {
Console.WriteLine(customer);
}
讓我們再次執行它,你將看到我們不會得到任何結果,如下所示。
Press <ENTER> to exit...
要理解為什麼我們沒有得到任何結果,讓我們看看 NHibernate Profiler。
正如你所看到的,FirstName 等於 A%,這不是。A% 用於 SQL 中的 like 運算子。現在我們需要在 WHERE 子句中建立一個限制,如下面的程式所示。
var customers = session.QueryOver<Customer>()
.Where(Restrictions.On<Customer>(c => c.FirstName).IsLike("A%"));
foreach (var customer in customers.List()) {
Console.WriteLine(customer);
}
讓我們再次執行你的應用程式,你將看到所有名字以 A 開頭的客戶都被檢索到。
Alejandrin Will (4ea3aef6-6bce-11e1-b0b4-6cf049ee52be)
Points: 24
HasGoldStatus: False
MemberSince: 10/1/2011 12:00:00 AM (Utc)
CreditRating: VeryVeryGood
AverageRating: 0
Orders:
Order Id: 4ea3aef6-6bce-11e1-b0b5-6cf049ee52be
Austyn Nolan (4ea871b6-6bce-11e1-b110-6cf049ee52be)
Points: 67
HasGoldStatus: True
MemberSince: 12/29/2007 12:00:00 AM (Utc)
CreditRating: Neutral
AverageRating: 0
Orders:
Order Id: 4ea871b6-6bce-11e1-b111-6cf049ee52be
Antonia Murphy (4ea871b6-6bce-11e1-b121-6cf049ee52be)
Points: 72
HasGoldStatus: True
MemberSince: 6/15/2009 12:00:00 AM (Utc)
CreditRating: Terrible
AverageRating: 0
Orders:
Order Id: 4ea871b6-6bce-11e1-b122-6cf049ee52be
Order Id: 4ea871b6-6bce-11e1-b123-6cf049ee52be
Order Id: 4ea871b6-6bce-11e1-b124-6cf049ee52be
Order Id: 4ea871b6-6bce-11e1-b125-6cf049ee52be
Order Id: 4ea871b6-6bce-11e1-b126-6cf049ee52be
Order Id: 4ea871b6-6bce-11e1-b127-6cf049ee52be
Order Id: 4ea871b6-6bce-11e1-b128-6cf049ee52be
Order Id: 4ea871b6-6bce-11e1-b129-6cf049ee52be
Order Id: 4ea871b6-6bce-11e1-b12a-6cf049ee52be
它的工作方式與之前相同,只是使用了新的 **QueryOver** 語法。許多開發人員發現 LINQ 語法更容易理解,並且通常能正確處理。
如果 LINQ 無法處理它,那麼你將開始檢視 HQL 或 Criteria,看看是否更合適。
它只提供了一種不同的語法,因此 Criteria(create criteria 和 QueryOver)都為你提供了另一種查詢機制,允許你使用 NHibernate 從資料庫中提取資料。