nhibernate-core icon indicating copy to clipboard operation
nhibernate-core copied to clipboard

Linq query produces wrong join types

Open IQS-Leopold opened this issue 5 years ago • 3 comments

There are cases when a linq query produces "inner joins" but a "left join" would be expected:

Version is: 5.3.5

Query

session.Query<TableA>()
    .Join(session.Query<TableB>(), a => a.X.F ?? a.Y.Z.F, b => b.F, (a,b) => new { A = a, B = b })
    .ToList();

this is producing the following query:

Current result

select *
  from TABLE_A a
  inner join TABLE_X x on a.FK1 = x.ID,
  inner join TABLE_Y y on a.FK2 = y.ID,
  inner join TABLE_Z z on y.FK3 = z.ID,
  inner join TABLE_B b on b.ID = coalesce(y.FK4, z.FK5)

But it would be expected that the property paths are interpreted as left joins. Sure it depends on the join condition but using the join type of the outer join is wrong.

Expected result

select *
  from TABLE_A a
  left join TABLE_X x on a.FK1 = x.ID,
  left join TABLE_Y y on a.FK2 = y.ID,
  left join TABLE_Z z on y.FK3 = z.ID,
  inner join TABLE_B b on b.ID = coalesce(y.FK4, z.FK5)

I have created a patch for my special case but I'm pretty sure it is the wrong place for the fix.

QueryModelVisitor.cs - Line 552

join = innerJoin ? _hqlTree.TreeBuilder.InnerJoin(joinExpression.AsExpression(), alias)
    : (HqlTreeNode) _hqlTree.TreeBuilder.LeftJoin(joinExpression.AsExpression(), alias);

Changed to:

QueryModelVisitor.cs - Line 552

join = innerJoin && joinClause.OuterKeySelector.NodeType != System.Linq.Expressions.ExpressionType.Coalesce
    ? _hqlTree.TreeBuilder.InnerJoin(joinExpression.AsExpression(), alias)
    : (HqlTreeNode) _hqlTree.TreeBuilder.LeftJoin(joinExpression.AsExpression(), alias);

Maybe someone can help.

IQS-Leopold avatar Nov 24 '20 07:11 IQS-Leopold

I believe the extension method LeftJoin would work in this case:

using NHibernate.Linq;

session.Query<TableA>()
    .LeftJoin(session.Query<TableB>(), a => a.X.F ?? a.Y.Z.F, b => b.F, (a,b) => new { A = a, B = b })
    .ToList();

Molinware avatar Feb 09 '21 19:02 Molinware

The inner join is expected and correct. That's how .Join is supposed to work.

Edit: Ok, you're saying that the property joins should be left joins. Possibly so.

gliljas avatar Feb 09 '21 20:02 gliljas

Suggested fix looks acceptable to me.

bahusoid avatar Aug 11 '21 11:08 bahusoid