hello, following the jira i've opened that explains the new feature: *
NH-2316 <http://216.121.112.228/browse/NH-2316>*
i've started working on it to hopefully upload a patch in the near future.
few issues with the current implementation of subselect fetching:
1. Its available only in the mappings, and not per criteria\hql query\linq
query\query over
2. It isn't overrideable with fetch mode lazy. the reason is that it is not
set for a specific query, but the persister of the collection, which is set
as fetch="subselect", is some special persister for sub select fetched
collections.
3. the query that is issued because of the subselect is very in-efficient.
if the first query is:
from Foo f
where f.Country.Region.Name = 'CoolRegion'
then the sub query created for foo.Children will be:
from Child c
where c.Foo.Id in
(select f.Id
from Foo f
where f.Country.Region.Name = 'CoolRegion')
notice that if the query on foo has joins\sub selects then the query that
gets foo's children is very inefficient, because after the query on foo was
executed
the ids of foo are available so the query could easily be
from Child c
where c.Foo.Id in (?,?,?...?
where the ? are the ids of the foos.
the 1 and 2 issues, make the subselect fetch unusuable when there are 2 use
cases, one where lazy is appropriate and one where subselect fetching is
appropriate
first of all, i'll be hapy to get your input about this.
fixing issue 3 was suprisingly easy,
i've just replaced the code in NHibernate.Engine.SubselectFetch that used to
take the query string of the original query to be used for the sub select
and replaced it with this code:
public SqlString ToSubselectString(string ukname)
{
SqlStringBuilder sqlBuilder = new SqlStringBuilder();
for (int i = 0; i < this.resultingEntityKeys.Count; i++)
{
if (i != 0)
{
sqlBuilder.Add(",");
}
sqlBuilder.AddParameter();
}
SqlString sqlString = sqlBuilder.ToSqlString();
return sqlString;
}
of course i also had to set the query parameters for the ids.
taking the ids of the original query was easy because they are already there
(in this.Results)
all unit tests pass so i think its ok.
about issues 1 and 2 - enabling a FetchMode.SubSelect, and in general,
making subselect a fetch mode just like join - i wanna start working on that
but first would like to know that you think all of this is a good idea and
if you have pointers on how to do it - because
for criteria its obvious - just use the FetchMode, for Linq its obvious -
there needs to be an extention method but for hql - should it be a methid of
IQuery or
should it be some token in the HQL?
for conclusion, i think that once implemented like that, it will be very
very easy to fetch a whole object graph for a paged query on the aggregate
root.
thanks in advance.
Nadav.