Here's a practical example.
Let's say that you have an online store and one of your domain classes is a Brand
like "Samsung". This class has a boatload of properties associated with it, perhaps an integer Identity
, a Name
, a free-text Description
field, a reference to a Vendor
object, and so on.
Now let's say that you want to display a menu with a list of all the brands offered on your online store. If you just do session.CreateCriteria<Brand>().List()
, then you are indeed going to get all of the brands. But you'll also have sucked all of the long Description
fields and references to Vendor
s from the database, and you don't need that to display a menu; you just need the Name
and the Identity
. Performance-wise, sucking all of this extra data down from the database slows things down and is unnecessary.
Instead, you can create a "projection" object that contains just the Identity
and the Name
calling it, say, NameIdentityPair
:
public class NameIdentityPair
{
public int Identity { get; set; }
public string Name { get; set; }
}
And you could tell NHibernate to only select the data that you really need to perform the task at hand by telling it to transform the result set onto your projection:
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);
}
Now you don't have a list of Brand
s but instead a list of NameIdentityPair
s, and NHibernate will have only issued a SQL statement like SELECT b.Identity, b.Name from dbo.Brand b
to obtain this projection, as opposed to a massive SQL statement that grabs everything necessary to hydrate a Brand
object (e.g., SELECT b.Identity, b.Name, b.Description from dbo.brand b left join dbo.vendor v ....
).
Hope this helps.
NameIdentityPair
object and map my result to it from the query, but using Projection, I instead specify the exact filtering I demand right in the query, and that is all the database is aware of? – Dougald