查詢所有擁有訂單的客戶。HQL/SQL 寫法:
// HQL
from Customer c where exists (from Order o where o.Customer = c.Id)
// SQL
select c.* from Customer c where exists (select 1 from `Order` o where o.Customer = c.CustomerId)
如何用 `ICriteria` + `Restrictions` 實現?
using NHibernate.Criterion;
// 主查詢
ICriteria criteria = session.CreateCriteria();
// 子查詢:關聯 Order,條件 Order.Customer = 外層 Customer.Id
DetachedCriteria orderSubquery = DetachedCriteria.For("o")
.Add(Property.ForName("o.Customer").EqProperty("c.Id")); // 關鍵:關聯外層別名 "c"
// 套用 EXISTS
criteria.Add(Subqueries.Exists(orderSubquery));
// 執行
IList list = criteria.List();
ICriteria criteria = session.CreateCriteria("c"); // 顯式別名 c
DetachedCriteria sub = DetachedCriteria.For("o")
.Add(Property.ForName("o.Customer").EqProperty("c.Id"));
criteria.Add(Subqueries.Exists(sub));
若資料量大,`EXISTS` 子查詢可能較慢。改用 `JOIN` + `DISTINCT_ROOT_ENTITY`:
ICriteria criteria = session.CreateCriteria("c")
.CreateAlias("c.Orders", "o", JoinType.InnerJoin) // 需 Customer 映射有 Orders 集合
.SetResultTransformer(CriteriaUtil.DistinctRootEntity); // 去重
// 等同:SELECT DISTINCT c.* FROM Customer c INNER JOIN Order o ON o.Customer = c.Id
StackOverflow 討論:NHibernate CreateCriteria and EXISTS clause
NHibernate Criteria 實現 EXISTS:**`DetachedCriteria` 定義子查詢 + `Property.EqProperty` 關聯外層別名 + `Subqueries.Exists()`**。記得顯式指定主查詢別名 (`CreateCriteria("c")`) 避免隱含別名問題。大資料量優先考慮 `JOIN` + `DistinctRootEntity`。