In this post, I’ll outline some basics on QueryOver, including the NHibernate types involved and basic query structure. I’ll also talk about joining using
This article is part of an ongoing series on NHibernate Queryover. Click here to see the table of contents.
If you look closely at the types involved when writing QueryOver queries, you’ll notice that there are two generic type parameters:
TSubType. Why would the API need two type parameters?
When you create a QueryOver object using
TSubType are the same.
TRoot stays the same as you build the query, and
TSubType changes as you use
JoinQueryOver to join to other tables. This is worth mentioning before we go into more depth on building queries.
- Operations except for
TSubTypeas the type parameter for lambda expressions you pass to QueryOver methods
TRootis the type parameter for lambda expressions you use in the
.Selectstep of the query.
Here’s an example:
session.QueryOver<Person>() // TRoot and TSubType are Person .JoinQueryOver(p => p.Addresses) // TRoot is Person, TSubtype is Address .Where(a => a.ModifiedDate == DateTime.Now) // Where accepts an Expression<Func<TSubtype, bool>> .Select(p => p.Id); // Select accepts an Expression<Func<TRoot, object>>
Since we’re on the subject of
TSubType, now is a good opportunity to talk about
JoinAlias adds a join to your query without changing
TSubType. This is useful if you’re joining to more than one table from a source table:
BusinessEntityAddress addressAlias = null; BusinessEntityContact contactAlias = null; session.QueryOver<Person>() .JoinAlias(p => p.Addresses, () => addressAlias) .JoinAlias(p => p.Contacts, () => contactAlias) .Where(p => p.FirstName == "Andrew") /* etc */
In this example, since we want to join to
Contact, we can use
JoinAlias twice, since
TSubType doesn’t change.
The second parameter (in this particular overload) to
.JoinAlias is a lambda expression that creates an alias. You can use the alias throughout the query in other lambda expressions when you don’t want to use either
JoinQueryOver adds a join to your query and changes
TSubType. You can also use an alias with
JoinQueryOver, but with simpler queries it’s often not necessary:
session.QueryOver<Person>() .JoinQueryOver(p => p.Addresses) .Where(a => a.ModifiedDate == DateTime.Now) .Select(p => p.FirstName)
Notice that the lambda expression passed to the
.Where method has the signature
Expression<Func<Address, bool>>. The call to
TSubType. This can make for more concise, easier to read code, since you don’t need to declare aliases for every join you do.
JoinQueryOver are interchangeable, as far as I know. You can write the same query using either one, it’s just that the number of aliases you declare changes based on which you use. Typically I choose whichever one avoids creating and managing more aliases. This means using
JoinQueryOver when possible, but that’s personal preference.
IQueryOveris a generic type with two type parameters
TRootwhile other QueryOver methods operate on
TRootstays the same as you’re building a query, but
TSubTypechanges when you join using
JoinAliasadd joins to your query.
- You can use aliases when building a query to refer to properties that don’t belong to