这是一个实际的例子。假设你有一个在线商店,其中一个域类别是“Brand”,如“三星”。这个类别有许多与之相关的属性,可能是一个整数“Identity”,一个“Name”,一个自由文本“Description”字段,一个对“Vendor”对象的引用等等。
现在假设你想显示一个菜单,列出在线商店提供的所有品牌。如果你只是做
session.CreateCriteria<Brand>().List()
,那么你确实会得到所有品牌。但你也会从数据库中吸取所有长的“Description”字段和对“Vendor”的引用,你并不需要这些来显示菜单;你只需要“Name”和“Identity”。就性能而言,从数据库中抽取所有这些额外的数据会拖慢速度并且是不必要的。
相反,你可以创建一个“projection”对象,它只包含“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
列表,而是一个NameIdentityPair
列表,NHibernate只会发出一个类似于SELECT b.Identity, b.Name from dbo.Brand b
的SQL语句来获得这个投影,而不是一条巨大的SQL语句来获取一个Brand
对象所需的所有内容(例如,SELECT b.Identity, b.Name, b.Description from dbo.brand b left join dbo.vendor v ....
)。
希望这可以帮助到你。
NameIdentityPair
对象,并将查询结果映射到它上面,但是使用投影,我可以直接在查询中指定精确的过滤条件,这就是数据库所知道的全部。 - Derek