cremor wrote:
How are you loading you main objects (first query)?
Because if you use something like the following, NHibernate will only execute one query to get all 30 objects.
Code:
session.CreateQuery(query).List<Type>();
Let's say I have object A with the following hibernate mapping:
A
- many-to-one B
- bag one-to-many C (inverse=true)
- bag one-to-many D (inverse=true)
- one-to-one E
- bag many-to-many F
- bag many-to-many G
Then I create the following HQL query
Code:
string queryString =
"select a " +
"from A as a " +
"join a.C as c " +
"join a.F as f " +
"where :value1 between c.Col1 and c.Col2 " +
"and c.Type = :value2 " +
"and c.Property >= :value3 " +
"and f.Property1 like :value4 " +
"and f.Property2 like :value5";
IQuery query = factory.Session.CreateQuery(queryString);
query.SetParameter("value1", value1);
query.SetParameter("value2", value2);
query.SetParameter("value3", value3);
query.SetParameter("value4", value4);
query.SetParameter("value5", value5);
IList<A> list = query.List<A>();
Hibernate sends the following SQL statements:
Code:
// first fetching all AIDs
select
a0_.[AID] as A1_29_,
a0_.[Property1] as Property12_29_,
a0_.[Property2] as Property23_29_
from
[dbo].[A] a0_
inner join [dbo].[C] c1_
on a0_.[AID]=c1_.[AID]
inner join F f2_
on a0_.[AID]=f2_.[AID]
inner join [dbo].[F] f3_
on f2_.[FID]=f3_.[FID]
where
(@p0 between c1_.[Col1] and c1_.[Col2] )
and(c1_.[Type]=@p1 )
and(c1_.[Property]>=@p2 )
and(f3_.[Property1] like @p3 )
and(f3_.[Property2] like @p4 )
// then fetching all "A"s again with the one-to-one relationship to E:
SELECT
e0_.[AID] as AID1_31_2_,
e0_.[Prop] as Prop2_31_2_,
a1_.[AID] as Restaura1_29_0_,
a1_.[Property1] as Property12_29_0_,
a1_.[Property2] as Property23_29_0_,
e2_.[AID] as AID1_31_1_,
e2_.[Prop] as Prop2_31_1_
FROM
[dbo].[E] e0_
left outer join [dbo].[A] a1_
on e0_.[AID]=a1_.[AID]
left outer join [dbo].[E] e2_
on a1_.[AID]=e2_.[AID]
WHERE
e0_.[AID]=@p0
cremor wrote:
And how are you mapping your bags?
I've never used bags myself, but for my sets and dictionaries NHibernate always executes only one query to get all objects in the list.
That's an example of a bag in my hibernate config:
Code:
<bag name="NameXYZ"
table="TableXYZ"
cascade="all-delete-orphan"
inverse="false" >
<key>
<column name= "`AID`" />
</key>
<many-to-many class="F"
fetch="join" >
<column name= "`FID`" />
</many-to-many>
</bag>
In the C# code I use an IList<F> with the Name NameXYZ for the property. When I access the property all elements in that list are loaded as you said.
However the problem is that every object A has the property NameXYZ. That means each time I access NameXYZ of one object A the elements are loaded. In my case 30 times on one page.
Instead of doing "SELECT ... FROM TableXYZ WHERE AID=@p0" it should do a "SELECT ... FROM TableXYZ WHERE AID=@p0 OR AID=@p1..." or "SELECT ... FROM TableXYZ WHERE AID IN (...)". Do you know what I mean?
Thanks,
Hilmar