I've got this object graph:
// Lots of stuff omitted for brevity; these are all virtual properties and there
// are other properties which aren't shown on all classes.
class A {
B b;
C c;
DateTime timestamp;
}
class B {
X x;
Y y;
}
class X {
int id;
}
class C { }
class Y { }
or to put it more simply,
a = {
b: {
x { id: int },
y: { }
},
c: { },
timestamp: DateTime
}
Now I'm making a query where I'm going to return a list of A
s and I need all their B
s, C
s, X
s and Y
s. I'm also going to group them by B into a lookup.
ILookup<B, A> GetData(List<int> ids) {
using (ISession session = OpenSession()) {
var query = from a in session.Query<A>()
where ids.Contains(a.b.x.id)
orderby A.timestamp descending
select a;
query = query
.Fetch(a => a.b)
.ThenFetch(b => b.x)
.Fetch(a => a.b)
.ThenFetch(b => b.y)
.Fetch(a => a.c);
return query.ToLookup(a => a.b);
}
}
A few things to note:
- This is a report where all data needs to be returned - unbounded results is not a problem.
- I'm doing the grouping by using
ToLookup
because usinggroup by
seems to be more complicated when you need all the actual values - you'd need to query the database for the groups and then for their actual values.
My question is how to specify the fetching strategy properly. The way I've done it is the only way I found for this to run (having fetched all of the b.x and b.y values) - but it produces SQL which seems wrong:
select /* snipped - every mapped field from a0, b1, x2, b3, y4, c5 - but not b6 */
from [A] a0
left outer join [B] b1
on a0.B_id = b1.BId
left outer join [X] x2
on b1.X_id = x2.XId
left outer join [B] b3
on a0.B_id = b3.BId
left outer join [Y] y4
on b3.Y_id = y4.YId
left outer join [C] c5
on a0.C_id = c5.CId,
[B] b6
where a0.B_id = b6.BId
and (b6.X_id in (1, 2, 3, 4, 5))
order by a0.timestamp desc
As you can see it's getting the value for a.b
3 times - b1
and b3
for the fetching, and b6
for the where clause.
- I assume this has a negative impact on DB performance - am I correct?
- Is there a way to modify my
.Fetch
calls so it only fetchesa.b
once? - Is this a good approach to my problem?