這裏有一個實際的例子。
假設你有一個在線商店,你的域類之一是Brand
如「三星」。這個類具有與它相關聯的屬性,可能的整數Identity
,一個Name
,自由文本字段Description
,到Vendor
對象的引用,等等的一船。
現在,讓我們說,你想在你的網上商店提供的所有品牌的列表中顯示的菜單。如果你只是做session.CreateCriteria<Brand>().List()
,那麼你確實會得到所有的品牌。但是您也可以從數據庫中吸取所有長Description
字段和對Vendor
的引用,並且不需要顯示菜單;你只需要Name
和Identity
。性能方面,從數據庫中吸收所有這些額外的數據會減慢速度並且不必要。
相反,你可以創建一個「投影」對象只包含Identity
和Name
調用它,也就是說,NameIdentityPair
:
public class NameIdentityPair
{
public int Identity { get; set; }
public string Name { get; set; }
}
你能告訴NHibernate的,只選擇你真正需要的數據告訴它的結果集轉換到您的投影來執行手頭的任務:
var brandProjections = this.session.CreateCriteria<Brand>()
.SetProjection(Projections.ProjectionList()
.Add(Projections.Property("Name"), "Name")
.Add(Projections.Property("Identity"), "Identity"))
.SetResultTransformer(Transformers.AliasToBean<NameIdentityPair>())
.List<NameIdentityPair>();
foreach (var brandProjection in brandProjections)
{
Console.WriteLine(
"Identity: {0}, Name: {1}",
brandProjection.Identity,
brandProjection.Name);
}
現在你沒有的Brand
個清單,但代替列表s,而NHibernate將只發佈一個SQL語句,如SELECT b.Identity, b.Name from dbo.Brand b
來獲得此投影,而不是大量的SQL語句,該語句抓取所有必需的東西來保存對象(例如SELECT b.Identity, b.Name, b.Description from dbo.brand b left join dbo.vendor v ....
)。
希望這會有所幫助。
所以投影就像查詢方限制器,查詢結果限制器的intead。在正常情況下,我會創建NameIdentityPair對象,並將查詢中的結果映射到查詢中,但是使用Projection時,我會指定恰好在查詢中要求的確切過濾條件,這是數據庫意識到的所有問題? – Derek 2011-05-26 15:25:52
許多應用程序的讀取次數比寫入次數多,因此常見模式是在從數據庫中讀取時使用投影,並使用完全水合的域對象保存到數據庫。通過這種方式,從數據庫中讀取數據會根據性能進行調整,並且寫入數據庫將被調整爲利用業務邏輯(寫入您的域類)和您正在使用的工具(NHibernate將您從大多數CRUD代碼中拯救出來)。 「投影」就像是抽出你需要的數據,這樣NHibernate只會在數據庫提交SQL時向數據庫請求數據。 – 2011-05-26 15:31:06
謝謝,我認爲這比迄今爲止發現的要清楚得多。 – Derek 2011-05-26 16:17:50