开发者

Why do these two NHibernate queries produce different results?

This is for a M:N relationship, with the collection being mapped in NHibernate as a Set.

The criteria query we were using previously "worked" but it did not populate the Skills collection properly, in that only the first/looking-for skill was brought down, even if the employee had multiple skills.

I changed it to a LINQ query and it fixes the issue, properly fetching all the skills of that employee.

Dim sId = 1 ' Just to have one for example
Dim lstEmployees = Session.CreateCriteria(Of Employee)() _
                    .CreateAlias("Skills", "s", NHibernate.SqlCommand.JoinType.LeftOuterJoin) _
                    .Add(Expression.Or(Expression.Eq("PrimarySkillId", sId),
                                       Expression.Eq("s.Id", sId))) _
                    .SetResultTransformer(New DistinctRootEntityResultTransformer()) _
                    .List(Of Employee)()

' Returns correct employees but only their first skill in the Skills collection, even if they have more than one

Dim lstEmployees = (From e In Session.Query(Of Employee)()
                  Where e.PrimarySkillId =sId OrElse e.Skills.Any(Function(s) s.Id = sId)
                  Select e Distinct).Fetch(Function(e) e.Skil开发者_如何学Pythonls).ToList()

' Returns correct employees and their Skills collection contains all of their skills

Does anyone understand what's different about the two seemingly-equivalent queries?


Off the bat, the first query is doing the distinct separation after retrieving all rows, while the second query actually does a select distinct .... What's likely happening is that it hydrates the Employee model with just the one Skill retrieved

To make the first query actually do a select distinct ... you will need to use projections.

Something like

Session.CreateCriteria(Of Employee)() _
       .CreateAlias("Skills", "s", NHibernate.SqlCommand.JoinType.LeftOuterJoin)
       .Add(Expression.Or(Expression.Eq("PrimarySkillId", sId),
                          Expression.Eq("s.Id", sId))) _
       .SetProjection(Projections.Distinct("Id")) _
       .SetFetchMode("s", FetchMode.Eager)

may work. Alternatively you can try to just set the fetch mode with the DistinctRootEntityResultTransformer

Session.CreateCriteria(Of Employee)() _
       .CreateAlias("Skills", "s", NHibernate.SqlCommand.JoinType.LeftOuterJoin)
       .Add(Expression.Or(Expression.Eq("PrimarySkillId", sId),
                          Expression.Eq("s.Id", sId))) _
       .SetResultTransformer(Transformers.DistinctRootEntityResultTransformer) _
       .SetFetchMode("s", FetchMode.Eager)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜