Skip to content

Commit 8899395

Browse files
committed
Use reference equality in InsertActionSorter
1 parent 88411b7 commit 8899395

File tree

7 files changed

+115
-4
lines changed

7 files changed

+115
-4
lines changed

src/NHibernate.Test/Async/Insertordering/AnimalModel/Fixture.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,5 +163,29 @@ public async System.Threading.Tasks.Task InsertShouldNotInitializeOneToManyProxy
163163
// instead.)
164164
}
165165
}
166+
167+
// #2141
168+
[Test]
169+
public async System.Threading.Tasks.Task InsertShouldNotDependOnEntityEqualsImplementationAsync()
170+
{
171+
var person = new PersonWithWrongEquals { Name = "AnimalOwner" };
172+
using (var s = OpenSession())
173+
using (var t = s.BeginTransaction())
174+
{
175+
await (s.SaveAsync(person));
176+
await (t.CommitAsync());
177+
}
178+
await (Sfi.EvictAsync(typeof(PersonWithWrongEquals)));
179+
180+
using (var s = OpenSession())
181+
using (var t = s.BeginTransaction())
182+
{
183+
var personProxy = await (s.GetAsync<PersonWithWrongEquals>(person.Id));
184+
185+
await (s.SaveAsync(new Cat { Name = "Felix", Owner = personProxy }));
186+
await (s.SaveAsync(new Cat { Name = "Loustic", Owner = personProxy }));
187+
Assert.DoesNotThrowAsync(() => { return t.CommitAsync(); });
188+
}
189+
}
166190
}
167191
}

src/NHibernate.Test/Insertordering/AnimalModel/Fixture.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,5 +153,29 @@ public void InsertShouldNotInitializeOneToManyProxy()
153153
// instead.)
154154
}
155155
}
156+
157+
// #2141
158+
[Test]
159+
public void InsertShouldNotDependOnEntityEqualsImplementation()
160+
{
161+
var person = new PersonWithWrongEquals { Name = "AnimalOwner" };
162+
using (var s = OpenSession())
163+
using (var t = s.BeginTransaction())
164+
{
165+
s.Save(person);
166+
t.Commit();
167+
}
168+
Sfi.Evict(typeof(PersonWithWrongEquals));
169+
170+
using (var s = OpenSession())
171+
using (var t = s.BeginTransaction())
172+
{
173+
var personProxy = s.Get<PersonWithWrongEquals>(person.Id);
174+
175+
s.Save(new Cat { Name = "Felix", Owner = personProxy });
176+
s.Save(new Cat { Name = "Loustic", Owner = personProxy });
177+
Assert.DoesNotThrow(() => { t.Commit(); });
178+
}
179+
}
156180
}
157181
}

src/NHibernate.Test/Insertordering/AnimalModel/Mappings.hbm.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,5 +61,11 @@
6161
<one-to-many class="SivasKangal"/>
6262
</bag>
6363
</subclass>
64+
<subclass name="PersonWithWrongEquals" discriminator-value="6">
65+
<bag name="SivasKangalsGeneric" lazy="true" inverse="true" cascade="save-update">
66+
<key column="OwnerId" />
67+
<one-to-many class="SivasKangal"/>
68+
</bag>
69+
</subclass>
6470
</class>
65-
</hibernate-mapping>
71+
</hibernate-mapping>
Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,24 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23

34
namespace NHibernate.Test.Insertordering.AnimalModel
45
{
56
public class PersonWithSivasKangals : Person
67
{
78
public virtual IList<SivasKangal> SivasKangalsGeneric { get; set; } = new List<SivasKangal>();
89
}
10+
11+
public class PersonWithWrongEquals : Person
12+
{
13+
public override bool Equals(object obj)
14+
{
15+
throw new ApplicationException("Equals call is unexpected.");
16+
}
17+
public override int GetHashCode()
18+
{
19+
throw new ApplicationException("GetHashCode call is unexpected.");
20+
}
21+
22+
public virtual IList<SivasKangal> SivasKangalsGeneric { get; set; } = new List<SivasKangal>();
23+
}
924
}

src/NHibernate/Async/Engine/ActionQueue.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using NHibernate.Action;
1919
using NHibernate.Cache;
2020
using NHibernate.Type;
21+
using NHibernate.Util;
2122

2223
namespace NHibernate.Engine
2324
{

src/NHibernate/Engine/ActionQueue.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using NHibernate.Action;
99
using NHibernate.Cache;
1010
using NHibernate.Type;
11+
using NHibernate.Util;
1112

1213
namespace NHibernate.Engine
1314
{
@@ -605,7 +606,7 @@ private class InsertActionSorter
605606
// The map of entities to their batch.
606607
private readonly Dictionary<object, int> _entityBatchNumber;
607608
// The map of entities to the latest batch (of another entities) they depend on.
608-
private readonly Dictionary<object, int> _entityBatchDependency = new Dictionary<object, int>();
609+
private readonly Dictionary<object, int> _entityBatchDependency = new Dictionary<object, int>(ReferenceComparer<object>.Instance);
609610

610611
// the map of batch numbers to EntityInsertAction lists
611612
private readonly Dictionary<int, List<AbstractEntityInsertAction>> _actionBatches = new Dictionary<int, List<AbstractEntityInsertAction>>();
@@ -619,7 +620,7 @@ public InsertActionSorter(ActionQueue actionQueue)
619620
_actionQueue = actionQueue;
620621

621622
//optimize the hash size to eliminate a rehash.
622-
_entityBatchNumber = new Dictionary<object, int>(actionQueue.insertions.Count + 1);
623+
_entityBatchNumber = new Dictionary<object, int>(actionQueue.insertions.Count + 1, ReferenceComparer<object>.Instance);
623624
}
624625

625626
// This sorting does not actually optimize some features like mapped inheritance or joined-table,
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
5+
namespace NHibernate.Util
6+
{
7+
/// <summary>
8+
/// Compares objects by reference equality
9+
/// </summary>
10+
/// <typeparam name="T"></typeparam>
11+
[Serializable]
12+
class ReferenceComparer<T> : IEqualityComparer, IEqualityComparer<T> where T : class
13+
{
14+
private ReferenceComparer()
15+
{
16+
}
17+
18+
public bool Equals(T x, T y)
19+
{
20+
return ReferenceEquals(x, y);
21+
}
22+
23+
public int GetHashCode(T obj)
24+
{
25+
return System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(obj);
26+
}
27+
28+
bool IEqualityComparer.Equals(object x, object y)
29+
{
30+
return ReferenceEquals(x, y);
31+
}
32+
33+
int IEqualityComparer.GetHashCode(object obj)
34+
{
35+
return System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(obj);
36+
}
37+
38+
public static readonly ReferenceComparer<T> Instance = new ReferenceComparer<T>();
39+
}
40+
}

0 commit comments

Comments
 (0)