This question is asking which of the two approaches below is more encouraged (and with what reasons)?
I am working with FluentNHibernate in a ServiceStack REST application using C# 4.0, but this question is general to NHibernate LINQ queries.
Is it more encouraged to:
(Method 1) quickly run a simple query which returns all rows where it matches the user’s id:
// Query the User by id
var user = session.Get<User>(request.UserId);
and then separately use LINQ on the returned List to further narrow down the results:
// 'User' contains a 'List<Location>'
var locations = user.Locations.Where(location =>
location.Timestamp >= (request.MinTimestamp.HasValue ? request.MinTimestamp.Value : 0) &&
location.Timestamp <= (request.MaxTimestamp.HasValue ? request.MaxTimestamp.Value : DateTime.Now.ToTimestamp()));
return locations;
(Method 2) or, is it more encouraged to run a more complicated query which does the above in a single query:
var locationsQuery = session.QueryOver<LocationModel>()
.Where(table => table.User.Id == request.UserId)
.And(table => table.Timestamp >= (request.MinTimestamp.HasValue ? request.MinTimestamp.Value : 0))
.And(table => table.Timestamp <= (request.MaxTimestamp.HasValue ? request.MaxTimestamp.Value : DateTime.Now.ToTimestamp()));
return locationsQuery.List();
if my goals are:
a) faster execution time
Benchmarks (revised)
Revised Complete Test Code: http://pastebin.com/0ykKwcxX
Benchmarks Output:
Method 1 took 147.291 seconds over 5000 iterations.
Query results of the last iteration:
{ Timestamp=1348659703485, Latitude=179.40000, Longitude=209.40000 }
{ Timestamp=1348659703486, Latitude=179.55000, Longitude=209.55000 }
{ Timestamp=1348659703487, Latitude=179.70000, Longitude=209.70000 }
{ Timestamp=1348659703488, Latitude=179.85000, Longitude=209.85000 }
{ Timestamp=1348659703489, Latitude=180.00000, Longitude=210.00000 }
Method 2 took 133.728 seconds over 5000 iterations.
Query results of the last iteration:
{ Timestamp=1348659703485, Latitude=179.40000, Longitude=209.40000 }
{ Timestamp=1348659703486, Latitude=179.55000, Longitude=209.55000 }
{ Timestamp=1348659703487, Latitude=179.70000, Longitude=209.70000 }
{ Timestamp=1348659703488, Latitude=179.85000, Longitude=209.85000 }
{ Timestamp=1348659703489, Latitude=180.00000, Longitude=210.00000 }
Difference: Method 2 was approximately 13.5 seconds faster.
b) long-term re-use and stability
If your goal is faster execution time then I’d have thought the second approach best as it does not do an unnecessary load of the User entity. Having said that, I’m not an NHibernate user so don’t know for sure, and to be certain, you should conduct some measured performance tests if it matters that much (“You can’t improve what you can’t measure” – can’t remember who said that but it’s a pretty good maxim).
Ayende has written a lot of good NHibernate posts worth looking at (e.g. http://ayende.com/blog/3988/nhibernate-the-difference-between-get-load-and-querying-by-id)
When it comes to ‘long term re-use and stability’ this kind of depends how you’re using this code. You could always refactor the query part so that your userid and timestamp filters are extension methods. See this post for an example: http://lostechies.com/jimmybogard/2012/08/30/evolutionary-project-structure/