Skip to content

Commit 3e353c1

Browse files
Fix orphan removal for detached one-to-one (#3406)
Related to #3403 Co-authored-by: Frédéric Delaporte <12201973+fredericDelaporte@users.noreply.github.com>
1 parent a0bc61f commit 3e353c1

File tree

6 files changed

+174
-2
lines changed

6 files changed

+174
-2
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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;
12+
using NUnit.Framework;
13+
14+
namespace NHibernate.Test.NHSpecificTest.GH3403OneToOne
15+
{
16+
using System.Threading.Tasks;
17+
[TestFixture]
18+
public class FixtureAsync : BugTestCase
19+
{
20+
private Guid _id;
21+
22+
protected override void OnSetUp()
23+
{
24+
using var session = OpenSession();
25+
using var transaction = session.BeginTransaction();
26+
var entity = new Entity1
27+
{
28+
Child = new Entity2()
29+
};
30+
31+
entity.Child.Parent = entity;
32+
33+
session.Save(entity);
34+
transaction.Commit();
35+
_id = entity.Id;
36+
}
37+
38+
protected override void OnTearDown()
39+
{
40+
using var session = OpenSession();
41+
using var transaction = session.BeginTransaction();
42+
session.CreateQuery("delete from System.Object").ExecuteUpdate();
43+
44+
transaction.Commit();
45+
}
46+
47+
[Test]
48+
public async Task OrphanDeleteForDetachedOneToOneAsync()
49+
{
50+
Guid childId;
51+
using (var session = OpenSession())
52+
using (var transaction = session.BeginTransaction())
53+
{
54+
var entity = await (session.GetAsync<Entity1>(_id));
55+
childId = entity.Child.Id;
56+
await (session.EvictAsync(entity.Child));
57+
entity.Child = null;
58+
59+
await (session.FlushAsync());
60+
await (transaction.CommitAsync());
61+
}
62+
63+
using (var session = OpenSession())
64+
{
65+
var entity = await (session.GetAsync<Entity1>(_id));
66+
Assert.That(entity, Is.Not.Null);
67+
Assert.That(entity.Child, Is.Null, "Unexpected child on parent");
68+
69+
var child = await (session.GetAsync<Entity2>(childId));
70+
Assert.That(child , Is.Null, "Child is still in database");
71+
}
72+
}
73+
}
74+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
3+
namespace NHibernate.Test.NHSpecificTest.GH3403OneToOne
4+
{
5+
public class Entity1
6+
{
7+
public virtual Guid Id { get; set; }
8+
9+
public virtual Entity2 Child { get; set; }
10+
}
11+
public class Entity2
12+
{
13+
public virtual Guid Id { get; set; }
14+
15+
public virtual Entity1 Parent { get; set; }
16+
}
17+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
using System;
2+
using NUnit.Framework;
3+
4+
namespace NHibernate.Test.NHSpecificTest.GH3403OneToOne
5+
{
6+
[TestFixture]
7+
public class Fixture : BugTestCase
8+
{
9+
private Guid _id;
10+
11+
protected override void OnSetUp()
12+
{
13+
using var session = OpenSession();
14+
using var transaction = session.BeginTransaction();
15+
var entity = new Entity1
16+
{
17+
Child = new Entity2()
18+
};
19+
20+
entity.Child.Parent = entity;
21+
22+
session.Save(entity);
23+
transaction.Commit();
24+
_id = entity.Id;
25+
}
26+
27+
protected override void OnTearDown()
28+
{
29+
using var session = OpenSession();
30+
using var transaction = session.BeginTransaction();
31+
session.CreateQuery("delete from System.Object").ExecuteUpdate();
32+
33+
transaction.Commit();
34+
}
35+
36+
[Test]
37+
public void OrphanDeleteForDetachedOneToOne()
38+
{
39+
Guid childId;
40+
using (var session = OpenSession())
41+
using (var transaction = session.BeginTransaction())
42+
{
43+
var entity = session.Get<Entity1>(_id);
44+
childId = entity.Child.Id;
45+
session.Evict(entity.Child);
46+
entity.Child = null;
47+
48+
session.Flush();
49+
transaction.Commit();
50+
}
51+
52+
using (var session = OpenSession())
53+
{
54+
var entity = session.Get<Entity1>(_id);
55+
Assert.That(entity, Is.Not.Null);
56+
Assert.That(entity.Child, Is.Null, "Unexpected child on parent");
57+
58+
var child = session.Get<Entity2>(childId);
59+
Assert.That(child , Is.Null, "Child is still in database");
60+
}
61+
}
62+
}
63+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernate.Test"
3+
namespace="NHibernate.Test.NHSpecificTest.GH3403OneToOne">
4+
<class name="Entity1">
5+
<id name="Id">
6+
<generator class="guid"/>
7+
</id>
8+
<one-to-one name="Child" cascade="all-delete-orphan" foreign-key="none" />
9+
</class>
10+
<class name="Entity2">
11+
<id name="Id">
12+
<generator class="foreign">
13+
<param name="property">Parent</param>
14+
</generator>
15+
</id>
16+
<one-to-one name="Parent" foreign-key="none" />
17+
</class>
18+
</hibernate-mapping>

src/NHibernate/Async/Engine/Cascade.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ private async Task CascadePropertyAsync(object parent, object child, IType type,
151151

152152
if (loadedValue != null)
153153
{
154-
await (eventSource.DeleteAsync(entry.Persister.EntityName, loadedValue, false, null, cancellationToken)).ConfigureAwait(false);
154+
await (eventSource.DeleteAsync(((EntityType) type).GetAssociatedEntityName(), loadedValue, false, null, cancellationToken)).ConfigureAwait(false);
155155
}
156156
}
157157
}

src/NHibernate/Engine/Cascade.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ private void CascadeProperty(object parent, object child, IType type, CascadeSty
203203

204204
if (loadedValue != null)
205205
{
206-
eventSource.Delete(entry.Persister.EntityName, loadedValue, false, null);
206+
eventSource.Delete(((EntityType) type).GetAssociatedEntityName(), loadedValue, false, null);
207207
}
208208
}
209209
}

0 commit comments

Comments
 (0)