Skip to content

Test for Merging a bidirectional list creates unnecessary UPDATE statement #1531

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions src/NHibernate.Test/Async/NHSpecificTest/GH1530/Fixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
//------------------------------------------------------------------------------
// <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 NHibernate.Cfg;
using NUnit.Framework;
using Environment = NHibernate.Cfg.Environment;

namespace NHibernate.Test.NHSpecificTest.GH1530
{
using System.Threading.Tasks;
[TestFixture]
public abstract class FixtureBaseAsync : BugTestCase
{
private Parent _parent;

protected override void OnSetUp()
{
using (var s = OpenSession())
{
using (var tx = s.BeginTransaction())
{
_parent = new Parent();
_parent.AddChild(new Child());
s.Save(_parent);
tx.Commit();
}
}
}

[Test]
public virtual async Task OneNewChildShouldOnlyCreateInsertWithNoUpdate_LockAndMergeAsync()
{
var parentClone = _parent.MakeCopy();
parentClone.AddChild(new Child());
using (var s = OpenSession())
{
using (var tx = s.BeginTransaction())
{
await (s.LockAsync(_parent, LockMode.None));
await (s.MergeAsync(parentClone));
s.SessionFactory.Statistics.Clear();
await (tx.CommitAsync());
}

Assert.That(s.SessionFactory.Statistics.PrepareStatementCount, Is.EqualTo(1));
}
}

[Test]
public virtual async Task OneNewChildShouldOnlyCreateInsertWithNoUpdate_MergeAsync()
{
var parentClone = _parent.MakeCopy();
parentClone.AddChild(new Child());
using (var s = OpenSession())
{
using (var tx = s.BeginTransaction())
{
await (s.MergeAsync(parentClone));
s.SessionFactory.Statistics.Clear();
await (tx.CommitAsync());
}

Assert.That(s.SessionFactory.Statistics.PrepareStatementCount, Is.EqualTo(1));
}
}

protected override void OnTearDown()
{
using (var s = OpenSession())
{
using (var tx = s.BeginTransaction())
{
s.Delete(s.Load<Parent>(_parent.Id));
tx.Commit();
}
}
}

protected override void Configure(Configuration configuration)
{
configuration.SetProperty(Environment.GenerateStatistics, "true");
}
}

[TestFixture]
public class FixtureAsync : FixtureBaseAsync
{
[Test]
[KnownBug("#1530")]
public override async Task OneNewChildShouldOnlyCreateInsertWithNoUpdate_MergeAsync()
{
await (base.OneNewChildShouldOnlyCreateInsertWithNoUpdate_MergeAsync());
}

[Test]
[KnownBug("#1530")]
public override async Task OneNewChildShouldOnlyCreateInsertWithNoUpdate_LockAndMergeAsync()
{
await (base.OneNewChildShouldOnlyCreateInsertWithNoUpdate_LockAndMergeAsync());
}
}

[TestFixture]
public class NonInverseFixtureAsync : FixtureBaseAsync
{
protected override string[] Mappings => new[] { "NonInverseMappings.hbm.xml" };
}

}
105 changes: 105 additions & 0 deletions src/NHibernate.Test/NHSpecificTest/GH1530/Fixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using NHibernate.Cfg;
using NUnit.Framework;
using Environment = NHibernate.Cfg.Environment;

namespace NHibernate.Test.NHSpecificTest.GH1530
{
[TestFixture]
public abstract class FixtureBase : BugTestCase
{
private Parent _parent;

protected override void OnSetUp()
{
using (var s = OpenSession())
{
using (var tx = s.BeginTransaction())
{
_parent = new Parent();
_parent.AddChild(new Child());
s.Save(_parent);
tx.Commit();
}
}
}

[Test]
public virtual void OneNewChildShouldOnlyCreateInsertWithNoUpdate_LockAndMerge()
{
var parentClone = _parent.MakeCopy();
parentClone.AddChild(new Child());
using (var s = OpenSession())
{
using (var tx = s.BeginTransaction())
{
s.Lock(_parent, LockMode.None);
s.Merge(parentClone);
s.SessionFactory.Statistics.Clear();
tx.Commit();
}

Assert.That(s.SessionFactory.Statistics.PrepareStatementCount, Is.EqualTo(1));
}
}

[Test]
public virtual void OneNewChildShouldOnlyCreateInsertWithNoUpdate_Merge()
{
var parentClone = _parent.MakeCopy();
parentClone.AddChild(new Child());
using (var s = OpenSession())
{
using (var tx = s.BeginTransaction())
{
s.Merge(parentClone);
s.SessionFactory.Statistics.Clear();
tx.Commit();
}

Assert.That(s.SessionFactory.Statistics.PrepareStatementCount, Is.EqualTo(1));
}
}

protected override void OnTearDown()
{
using (var s = OpenSession())
{
using (var tx = s.BeginTransaction())
{
s.Delete(s.Load<Parent>(_parent.Id));
tx.Commit();
}
}
}

protected override void Configure(Configuration configuration)
{
configuration.SetProperty(Environment.GenerateStatistics, "true");
}
}

[TestFixture]
public class Fixture : FixtureBase
{
[Test]
[KnownBug("#1530")]
public override void OneNewChildShouldOnlyCreateInsertWithNoUpdate_Merge()
{
base.OneNewChildShouldOnlyCreateInsertWithNoUpdate_Merge();
}

[Test]
[KnownBug("#1530")]
public override void OneNewChildShouldOnlyCreateInsertWithNoUpdate_LockAndMerge()
{
base.OneNewChildShouldOnlyCreateInsertWithNoUpdate_LockAndMerge();
}
}

[TestFixture]
public class NonInverseFixture : FixtureBase
{
protected override string[] Mappings => new[] { "NonInverseMappings.hbm.xml" };
}

}
25 changes: 25 additions & 0 deletions src/NHibernate.Test/NHSpecificTest/GH1530/Mappings.hbm.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="NHibernate.Test.NHSpecificTest.GH1530"
assembly="NHibernate.Test">
<class name="Parent">
<id name="Id" type="guid">
<generator class="guid.comb"/>
</id>
<list name="Children" cascade="all-delete-orphan" inverse="true">
<key column="Parent" not-null="true"/>
<list-index column="OrderIndex"/>
<one-to-many class="Child"/>
</list>
<property name="Name"/>
</class>

<class name="Child">
<id name="Id" type="guid">
<generator class="guid.comb"/>
</id>
<many-to-one name="Parent" class="Parent"/>
<property name="OrderIndex" access="readonly"/>
<property name="Name"/>
</class>
</hibernate-mapping>
66 changes: 66 additions & 0 deletions src/NHibernate.Test/NHSpecificTest/GH1530/Model.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;

namespace NHibernate.Test.NHSpecificTest.GH1530
{
public class Parent
{
public virtual Guid Id { get; set; }
public virtual IList<Child> Children { get; set; } = new List<Child>();
public virtual string Name { get; set; } = Guid.NewGuid().ToString();

public virtual void AddChild(Child child)
{
Children.Add(child);
child.Parent = this;
}

public virtual Parent MakeCopy()
{
var ret = new Parent { Id = Id, Name = Name };
foreach (var child in Children)
{
ret.AddChild(new Child { Id = child.Id, Name = child.Name });
}

return ret;
}

public override bool Equals(object obj)
{
return obj is Parent other && Id == other.Id;
}

public override int GetHashCode()
{
return 0;
}
}

public class Child
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; } = Guid.NewGuid().ToString();
public virtual Parent Parent { get; set; }

public virtual int OrderIndex
{
get
{
if (Parent == null)
return -2;
return Parent.Children.IndexOf(this);
}
}

public override bool Equals(object obj)
{
return obj is Child other && Id == other.Id;
}

public override int GetHashCode()
{
return 0;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="NHibernate.Test.NHSpecificTest.GH1530"
assembly="NHibernate.Test">
<class name="Parent">
<id name="Id" type="guid">
<generator class="guid.comb"/>
</id>
<list name="Children" cascade="all-delete-orphan">
<key column="Parent" not-null="true" update="false"/>
<list-index column="OrderIndex"/>
<one-to-many class="Child"/>
</list>
<property name="Name"/>
</class>


<class name="Child">
<id name="Id" type="guid">
<generator class="guid.comb"/>
</id>
<many-to-one name="Parent" class="Parent" update="false" insert="false"/>
<property name="Name"/>
</class>
</hibernate-mapping>