so here’s the situation: suppose I have a class structure used to represent flexible search:
public class SearchDefinition
{
public virtual string Name {get; set;}
public virtual IEnumerable<SearchTerm> Terms {get; set;}
}
public abstract class SearchTerm
{
public virtual Operator Op {get; set; } //i.e 'In', 'Not in', 'Contains' etc..
public abstract IEnumerable<object> CompareValues {get; } //the values against which the search is performed. for example- 'in (2,6,4)', 'contains ('foo', 'blah')'.
}
now, since search terms can refer to different fields, each type of term has its own class:
public class NameSearchTerm : SearchTerm
{
public virtual IEnumberable<string> ConcreteValues {get; set;}
public override IEnumberable<object> CompareValues
{
get
{
return ConcreteValues.Cast<object>();
}
}
}
and so on, with collections of different types.
Terms are mapped using table-per-heirarchy, except for the ConcreteValues collections, which are mapped to different tables (a table for string values, a table for int values etc..).
my question is- how do I efficiently retrieve a list of SearchDefinitions? for the collection of SearchTerms I can’t use select strategy (will result in select N+1).
However, fetching using JoinQueryOver or JoinAlias, while sending the correct query, does not populate the collection:
var definitions = session.QueryOver<SearchDefinition>()
.Where(/*condition*/)
.JoinAlias(d=> d.Terms, () => termsAlias)
.List(); //sends a correct, joined query which fetches also the terms from the terms table
Assert.IsTrue(NHibernateUtil.IsInitialized(definitions[0].Terms)); //THIS FAILS!
any suggestions on how to do this?
I’m adding the fluent mappings here-
the terms collection inside the SearchDefinition class:
mapping.HasMany(x => x.Terms)
//.Not.LazyLoad()
.Fetch.Subselect()
.Cascade.AllDeleteOrphan()
.Cache.ReadWrite();
the Concrete values collection inside the IntSearchTerm class (similar for all term classes):
mapping.HasMany<int>(t=> t.ConcreteValues).Table("TermsIntValues").Element("IntValue")
//.Not.LazyLoad()
.Fetch.Subselect()
.Cascade.AllDeleteOrphan();
the thing is that once the fetching strategy in the mapping file is defined as ‘SubSelect’, initializing one type of collection would initialize it on all objects that contain that type of collection.
See the follwing working code for further details: