I am attempting to teach myself NHibernate after working exclusively with Entity Framework for a few years now. I know how I would write the query, and I know how I would write the code with EF and lambda expressions, but translating that to NHibernate is stumping me.
The query would be written as:
SELECT fb.*
FROM foo f
INNER JOIN bar b ON f.fooid = b.fooid
INNER JOIN foobar fb ON b.barid = fb.barid
WHERE f.otherid = 1
Basically, I know a key of my start table ( foo
), and I want to return all of the matching rows in the 2nd joined table ( foobar
). In EF, I would write:
public IEnumerable<foobar> GetFooBarInfo(int intFooID)
{
return db.foo.Include(f => f.bar)
.Include(fb => fb.bar.foobar)
.Where(f => f.otherentity.fooid == intFooID)
.Select(fb => fb.bar.foobar)
.ToList();
}
Now converting that to NHibernate is where I need help. I have tried a few things, none of which I've saved, but the latest version returns 1 row instead of 7 rows. It looks like it is returning the one row in foobar
where barid = 1
instead of all barid
values where fooid = 1
.
public IEnumerable<foobar> GetFooBarInfo(int intFooID)
{
foo f = null;
bar b = null;
foobar fb = null;
return db.QueryOver<foo>(() => f)
.Where(fi => fi.otherentity.fooid == intFooID)
.Inner.JoinQueryOver(ba => ba.bar, () => b)
.Inner.JoinQueryOver(fbar => fbar.foobar, () => fb)
.Select(Projections.ProjectionList()
.Add(Projections.Property(() => fb.barid))
.Add(Projections.Property(() => fb.barname))
.Add(Projections.Property(() => fb.bardescription))
)
.TransformUsing(Transformers.AliasToBean<foobar>())
.List<foobar>();
}
I also just realized that it isn't truly filling the projection/transform. barid
is 0 and barname
and bardescription
are null - these obviously have values in the database.
I was attempting to join foo
and bar
on fooid
, but bar
had its own primary key foobarid
. Once I turned on logging for NHibernate, I could see the generated query was incorrect . It was generating:
SELECT fb.*
FROM foo f
INNER JOIN bar b ON f.fooid = b.foobarid
INNER JOIN foobar fb ON b.barid = fb.barid
WHERE f.otherid = 1
So then I realized I needed to include the parent table for bar
, which was baz
in order to get the join right. But this meant I needed to make the map for baz
include:
.HasMany(x => x.bar).KeyColumn("fooid")
.HasMany(x => x.foobar).KeyColumn("barid")
Then alter the QueryOver
to include this additional table. This got the result count right, but still wasn't projecting into the object properly - everything was null until I added the string alias on each Projection.Property()
:
public IEnumerable<foobar> GetFooBarInfo(int intFooID)
{
foo f = null;
bar b = null;
baz bz = null;
foobar fb = null;
return db.QueryOver<foo>(() => f)
.Where(fi => fi.otherentity.fooid == intFooID)
.Inner.JoinQueryOver(bb => bb.baz, () => bz)
.Inner.JoinQueryOver(ba => ba.bar, () => b)
.Inner.JoinQueryOver(fbar => fbar.foobar, () => fb)
.Select(Projections.ProjectionList()
.Add(Projections.Property(() => fb.barid), "barid")
.Add(Projections.Property(() => fb.barname), "barname")
.Add(Projections.Property(() => fb.bardescription), "bardescription")
)
.TransformUsing(Transformers.AliasToBean<foobar>())
.List<foobar>();
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.