Skip to content

Commit c70cdcf

Browse files
authored
Fix NRE with reused fetch and collection join (nhibernate#3314)
Fixes nhibernate#3288
1 parent 19d4549 commit c70cdcf

File tree

5 files changed

+163
-1
lines changed

5 files changed

+163
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by AsyncGenerator.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if
6+
// the code is regenerated.
7+
// </auto-generated>
8+
//------------------------------------------------------------------------------
9+
10+
11+
using System.Linq;
12+
using NHibernate.Linq;
13+
using NUnit.Framework;
14+
15+
namespace NHibernate.Test.NHSpecificTest.GH3288
16+
{
17+
using System.Threading.Tasks;
18+
[TestFixture]
19+
public class FetchAndCollectionJoinFixtureAsync : BugTestCase
20+
{
21+
protected override void OnSetUp()
22+
{
23+
using var session = OpenSession();
24+
using var transaction = session.BeginTransaction();
25+
var middleEntity = new MiddleEntity();
26+
middleEntity.Components.Add(new Component { MiddleEntity = middleEntity, Value = 1 });
27+
var te = new TopEntity
28+
{
29+
MiddleEntity = middleEntity
30+
};
31+
session.Save(middleEntity);
32+
session.Save(te);
33+
34+
transaction.Commit();
35+
}
36+
37+
protected override void OnTearDown()
38+
{
39+
using var session = OpenSession();
40+
using var transaction = session.BeginTransaction();
41+
session.Delete("from System.Object");
42+
43+
transaction.Commit();
44+
}
45+
46+
[Test]
47+
public async Task ReuseEntityJoinWithCollectionJoinAsync()
48+
{
49+
using var session = OpenSession();
50+
51+
var entities = await (session.Query<TopEntity>()
52+
.Fetch(e => e.MiddleEntity)
53+
.Where(e => e.MiddleEntity.Components.Any(e => e.Value != 0))
54+
.ToListAsync());
55+
Assert.That(entities.Count, Is.EqualTo(1));
56+
}
57+
}
58+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System.Collections.Generic;
2+
3+
namespace NHibernate.Test.NHSpecificTest.GH3288
4+
{
5+
class TopEntity
6+
{
7+
public virtual int Id { get; set; }
8+
public virtual MiddleEntity MiddleEntity { get; set; }
9+
}
10+
class MiddleEntity
11+
{
12+
public virtual int Id { get; set; }
13+
public virtual ISet<Component> Components { get; set; } = new HashSet<Component>();
14+
}
15+
16+
class Component
17+
{
18+
public virtual MiddleEntity MiddleEntity { get; set; }
19+
public virtual int Value { get; set; }
20+
21+
public override bool Equals(object obj)
22+
{
23+
return (obj as Component)?.MiddleEntity.Id == MiddleEntity.Id;
24+
}
25+
26+
public override int GetHashCode()
27+
{
28+
return MiddleEntity.Id.GetHashCode();
29+
}
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using System.Linq;
2+
using NHibernate.Linq;
3+
using NUnit.Framework;
4+
5+
namespace NHibernate.Test.NHSpecificTest.GH3288
6+
{
7+
[TestFixture]
8+
public class FetchAndCollectionJoinFixture : BugTestCase
9+
{
10+
protected override void OnSetUp()
11+
{
12+
using var session = OpenSession();
13+
using var transaction = session.BeginTransaction();
14+
var middleEntity = new MiddleEntity();
15+
middleEntity.Components.Add(new Component { MiddleEntity = middleEntity, Value = 1 });
16+
var te = new TopEntity
17+
{
18+
MiddleEntity = middleEntity
19+
};
20+
session.Save(middleEntity);
21+
session.Save(te);
22+
23+
transaction.Commit();
24+
}
25+
26+
protected override void OnTearDown()
27+
{
28+
using var session = OpenSession();
29+
using var transaction = session.BeginTransaction();
30+
session.Delete("from System.Object");
31+
32+
transaction.Commit();
33+
}
34+
35+
[Test]
36+
public void ReuseEntityJoinWithCollectionJoin()
37+
{
38+
using var session = OpenSession();
39+
40+
var entities = session.Query<TopEntity>()
41+
.Fetch(e => e.MiddleEntity)
42+
.Where(e => e.MiddleEntity.Components.Any(e => e.Value != 0))
43+
.ToList();
44+
Assert.That(entities.Count, Is.EqualTo(1));
45+
}
46+
}
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
2+
namespace="NHibernate.Test.NHSpecificTest.GH3288"
3+
assembly="NHibernate.Test">
4+
<class name="TopEntity" table="`TopEntity`">
5+
<id name="Id" >
6+
<generator class="identity" />
7+
</id>
8+
<many-to-one class="MiddleEntity" name="MiddleEntity">
9+
<column name="MiddleEntity_id" />
10+
</many-to-one>
11+
</class>
12+
<class name="MiddleEntity" table="`MiddleEntity`">
13+
<id name="Id" >
14+
<generator class="identity" />
15+
</id>
16+
<set cascade="all" name="Components" table="BottomEntity">
17+
<key not-null="true">
18+
<column name="MiddleEntity_id" />
19+
</key>
20+
<composite-element class="Component">
21+
<parent name="MiddleEntity" />
22+
<property name="Value" column="`Value`" />
23+
</composite-element>
24+
</set>
25+
</class>
26+
</hibernate-mapping>

src/NHibernate/Hql/Ast/ANTLR/HqlSqlWalker.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ internal string GetEntitySuffix(FromElement fromElement)
527527

528528
internal string GetCollectionSuffix(FromElement fromElement)
529529
{
530-
if (!fromElement.CollectionJoin && fromElement.QueryableCollection == null)
530+
if (fromElement.QueryableCollection == null)
531531
{
532532
return null;
533533
}

0 commit comments

Comments
 (0)