Skip to content

Commit

Permalink
Fix orphan removal for detached one-to-one (#3406)
Browse files Browse the repository at this point in the history
Related to #3403

Co-authored-by: Frédéric Delaporte <12201973+fredericDelaporte@users.noreply.github.com>
  • Loading branch information
bahusoid and fredericDelaporte committed Aug 15, 2023
1 parent a0bc61f commit 3e353c1
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 2 deletions.
74 changes: 74 additions & 0 deletions src/NHibernate.Test/Async/NHSpecificTest/GH3403OneToOne/Fixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by AsyncGenerator.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------


using System;
using NUnit.Framework;

namespace NHibernate.Test.NHSpecificTest.GH3403OneToOne
{
using System.Threading.Tasks;
[TestFixture]
public class FixtureAsync : BugTestCase
{
private Guid _id;

protected override void OnSetUp()
{
using var session = OpenSession();
using var transaction = session.BeginTransaction();
var entity = new Entity1
{
Child = new Entity2()
};

entity.Child.Parent = entity;

session.Save(entity);
transaction.Commit();
_id = entity.Id;
}

protected override void OnTearDown()
{
using var session = OpenSession();
using var transaction = session.BeginTransaction();
session.CreateQuery("delete from System.Object").ExecuteUpdate();

transaction.Commit();
}

[Test]
public async Task OrphanDeleteForDetachedOneToOneAsync()
{
Guid childId;
using (var session = OpenSession())
using (var transaction = session.BeginTransaction())
{
var entity = await (session.GetAsync<Entity1>(_id));
childId = entity.Child.Id;
await (session.EvictAsync(entity.Child));
entity.Child = null;

await (session.FlushAsync());
await (transaction.CommitAsync());
}

using (var session = OpenSession())
{
var entity = await (session.GetAsync<Entity1>(_id));
Assert.That(entity, Is.Not.Null);
Assert.That(entity.Child, Is.Null, "Unexpected child on parent");

var child = await (session.GetAsync<Entity2>(childId));
Assert.That(child , Is.Null, "Child is still in database");
}
}
}
}
17 changes: 17 additions & 0 deletions src/NHibernate.Test/NHSpecificTest/GH3403OneToOne/Entity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;

namespace NHibernate.Test.NHSpecificTest.GH3403OneToOne
{
public class Entity1
{
public virtual Guid Id { get; set; }

public virtual Entity2 Child { get; set; }
}
public class Entity2
{
public virtual Guid Id { get; set; }

public virtual Entity1 Parent { get; set; }
}
}
63 changes: 63 additions & 0 deletions src/NHibernate.Test/NHSpecificTest/GH3403OneToOne/Fixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System;
using NUnit.Framework;

namespace NHibernate.Test.NHSpecificTest.GH3403OneToOne
{
[TestFixture]
public class Fixture : BugTestCase
{
private Guid _id;

protected override void OnSetUp()
{
using var session = OpenSession();
using var transaction = session.BeginTransaction();
var entity = new Entity1
{
Child = new Entity2()
};

entity.Child.Parent = entity;

session.Save(entity);
transaction.Commit();
_id = entity.Id;
}

protected override void OnTearDown()
{
using var session = OpenSession();
using var transaction = session.BeginTransaction();
session.CreateQuery("delete from System.Object").ExecuteUpdate();

transaction.Commit();
}

[Test]
public void OrphanDeleteForDetachedOneToOne()
{
Guid childId;
using (var session = OpenSession())
using (var transaction = session.BeginTransaction())
{
var entity = session.Get<Entity1>(_id);
childId = entity.Child.Id;
session.Evict(entity.Child);
entity.Child = null;

session.Flush();
transaction.Commit();
}

using (var session = OpenSession())
{
var entity = session.Get<Entity1>(_id);
Assert.That(entity, Is.Not.Null);
Assert.That(entity.Child, Is.Null, "Unexpected child on parent");

var child = session.Get<Entity2>(childId);
Assert.That(child , Is.Null, "Child is still in database");
}
}
}
}
18 changes: 18 additions & 0 deletions src/NHibernate.Test/NHSpecificTest/GH3403OneToOne/Mappings.hbm.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernate.Test"
namespace="NHibernate.Test.NHSpecificTest.GH3403OneToOne">
<class name="Entity1">
<id name="Id">
<generator class="guid"/>
</id>
<one-to-one name="Child" cascade="all-delete-orphan" foreign-key="none" />
</class>
<class name="Entity2">
<id name="Id">
<generator class="foreign">
<param name="property">Parent</param>
</generator>
</id>
<one-to-one name="Parent" foreign-key="none" />
</class>
</hibernate-mapping>
2 changes: 1 addition & 1 deletion src/NHibernate/Async/Engine/Cascade.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ private async Task CascadePropertyAsync(object parent, object child, IType type,

if (loadedValue != null)
{
await (eventSource.DeleteAsync(entry.Persister.EntityName, loadedValue, false, null, cancellationToken)).ConfigureAwait(false);
await (eventSource.DeleteAsync(((EntityType) type).GetAssociatedEntityName(), loadedValue, false, null, cancellationToken)).ConfigureAwait(false);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/NHibernate/Engine/Cascade.cs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ private void CascadeProperty(object parent, object child, IType type, CascadeSty

if (loadedValue != null)
{
eventSource.Delete(entry.Persister.EntityName, loadedValue, false, null);
eventSource.Delete(((EntityType) type).GetAssociatedEntityName(), loadedValue, false, null);
}
}
}
Expand Down

0 comments on commit 3e353c1

Please sign in to comment.