How to Make Linq to NHibernate’s Expand() Type Safe
Linq to NHibernate is great. It makes your queries so much easier to understand since it expresses the intent of what you are doing better than the CreateCriteria API does.
For example compare this statement:
with this:
To me, the second is much easier to read, especially if you have people who aren’t familiar with NHibernate trying to read your code. The only problem with both of these queries is the use of those nasty magic strings. What happens if I refactor my UserProfile class and rename the Sites collection to something like PublicSites? Obviously my query will no longer work as expected but I’d only find that out when I ran my integration tests (or at run time if I happened to be lazy and don’t write tests).
I want to avoid all that magic string nastiness and lean on the compiler to help me out, so I planned to write some extension methods to improve the situation, but do that and reinvent the wheel? After all, Marcin Budny has done all that wheel-inventing already and made the extension methods available from his blog. Sweet!
Now I can get rid of that “Sites” magic string and write strongly typed code that looks like this:
Isn’t that so much nicer :-) Thanks Marcin for making your code available!
For example compare this statement:
var query = session.CreateCriteria<UserProfile>()
.Add(Restrictions.Eq("Id", identifier))
.SetFetchMode("Sites"), FetchMode.Join);
var result = query.UniqueResult<userprofile>();
with this:
var query = from p in session.Linq<UserProfile>().Expand("Sites")
where p.Identifier.Equals(identifier)
select p;
var result = query.SingleOrDefault();
To me, the second is much easier to read, especially if you have people who aren’t familiar with NHibernate trying to read your code. The only problem with both of these queries is the use of those nasty magic strings. What happens if I refactor my UserProfile class and rename the Sites collection to something like PublicSites? Obviously my query will no longer work as expected but I’d only find that out when I ran my integration tests (or at run time if I happened to be lazy and don’t write tests).
I want to avoid all that magic string nastiness and lean on the compiler to help me out, so I planned to write some extension methods to improve the situation, but do that and reinvent the wheel? After all, Marcin Budny has done all that wheel-inventing already and made the extension methods available from his blog. Sweet!
Now I can get rid of that “Sites” magic string and write strongly typed code that looks like this:
var query = from p in session.Linq<UserProfile>().Expand(u => u.Sites)
where p.Identifier.Equals(identifier)
select p;
var result = query.FirstOrDefault();
Isn’t that so much nicer :-) Thanks Marcin for making your code available!