I am using Linq2NHibernate to fetch a bunch of data from a table in several queries. Although the table contains 10 columns, I am only using 3 of them in my query, and I don’t need other properties afterwards. Generated SQL nevertheless loads (as expected) all properties on each query.
What is the recommended way to optimize the query?
Does it make sense to make lighter entity variants to be used for optimized queries? I.e. to create an entity containing only 2 properties, and map it to the same table? If the actual entity inherits from the lighter entity, it shouldn’t make too much mess, and NHibernate would end up fetching only the smaller subset of data.
Is this common practice, or is there a better way to optimize queries? I would prefer to stick to LINQ, since it is used throughout the project right now.
[Edit]
As Mike answered below, the solution is pretty obvious: actual projected DTOs will dictate the necessary properties to fetch. So I will provide an example, just to make it clearer:
In other words, this query will load all properties:
/* fetch actual entities */
var results = session
.Query<Food>()
.Where(p => p.Proteins < 100 && p.Fats < 50);
/* ... results in: */
SELECT Id, Proteins, Fats, Carbs, Name, Whatever
FROM [Food] WHERE Proteins < 100 AND Fats < 50
While this one will generate the query to fetch only the projected properties:
/* fetch light DTOs */
var results = session
.Query<Food>()
.Where(p => p.Proteins < 100 && p.Fats < 50)
.Select(p => new
{
Proteins = p.Proteins,
Fats = p.Fats
});
/* generated sql: */
SELECT Proteins, Fats
FROM [Food] WHERE Proteins < 100 AND Fats < 50
Since you haven’t posted your actual query it’s difficult to see what the problem is. Typically, you would populate a data transfer object (DTO) with only the fields you require. That will fix one issue. As for your LINQ query including every field in your domain entity you have to use projections. Projections will tell NHibernate to only fetch those excluding the rest of your domain. Note that I don’t query NHibernate with LINQ but the concepts are the same.
As an aside I do agree with Matías Fidemraizer that you should consider using the new QueryOver API.