Skip to content
Open
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
85 changes: 85 additions & 0 deletions src/NHibernate.Test/Async/NHSpecificTest/GH3539/Fixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
//------------------------------------------------------------------------------
// <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;

namespace NHibernate.Test.NHSpecificTest.GH3539
{
using System.Threading.Tasks;
[TestFixture]
public class FixtureAsync : BugTestCase
{
protected override void Configure(Configuration configuration)
{
configuration.SetProperty(Cfg.Environment.GenerateStatistics, "true");
}

protected override void OnTearDown()
{
using (var s = Sfi.OpenSession())
using (var t = s.BeginTransaction())
{
s.Delete("from Person");
t.Commit();
}

base.OnTearDown();
}

[Test]
public async Task TestComponentAsync()
{
int personId;
using (var s = Sfi.OpenSession())
using (var t = s.BeginTransaction())
{
var person = new Person(age: 20)
{
CardInfo = new("card1", "card2")
};
await (s.SaveAsync(person));
await (t.CommitAsync());
await (s.FlushAsync());
personId = person.Id;
}

using (var s = Sfi.OpenSession())
using (var t = s.BeginTransaction())
{
var restored = await (s.GetAsync<Person>(personId));

var oldCardInfo = restored.CardInfo;

Assert.That(oldCardInfo.GetCardsCopy().Contains("card1"));
Assert.That(oldCardInfo.GetCardsCopy().Contains("card2"));

var newCardInfo = new CardInfo("card1", "card2");

Assert.That(oldCardInfo.GetHashCode(), Is.EqualTo(newCardInfo.GetHashCode()));
Assert.That(oldCardInfo.Equals(newCardInfo));

restored.CardInfo = newCardInfo;

// Expected behaviour:
//
// At this point there should be no DML statements because newCardInfo
// is the same as the old one. But NHibernate will generate DELETE
// followed by 2 INSERT into OldCards table.

using (var x = new SqlLogSpy())
{
await (t.CommitAsync());
Assert.That(x.GetWholeLog(), Is.Empty);
}
}
}
}
}
47 changes: 47 additions & 0 deletions src/NHibernate.Test/NHSpecificTest/GH3539/CardInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace NHibernate.Test.NHSpecificTest.GH3539;

public class CardInfo
{
private readonly ISet<string> _oldCards;

protected CardInfo() { }

public CardInfo(params string[] cards)
{
_oldCards = cards.ToHashSet();
}

public virtual ISet<string> GetCardsCopy()
{
return _oldCards.ToHashSet();
}

public override bool Equals(object obj)
{
if (obj is null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
if (obj.GetType() != GetType())
{
return false;
}
var other = (CardInfo) obj;
return _oldCards.SetEquals(other._oldCards);
}

public override int GetHashCode()
{
var hashCode = new HashCode();
foreach (var card in _oldCards) hashCode.Add(card);
return hashCode.ToHashCode();
}
}
74 changes: 74 additions & 0 deletions src/NHibernate.Test/NHSpecificTest/GH3539/Fixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using NHibernate.Cfg;
using NUnit.Framework;

namespace NHibernate.Test.NHSpecificTest.GH3539
{
[TestFixture]
public class Fixture : BugTestCase
{
protected override void Configure(Configuration configuration)
{
configuration.SetProperty(Cfg.Environment.GenerateStatistics, "true");
}

protected override void OnTearDown()
{
using (var s = Sfi.OpenSession())
using (var t = s.BeginTransaction())
{
s.Delete("from Person");
t.Commit();
}

base.OnTearDown();
}

[Test]
public void TestComponent()
{
int personId;
using (var s = Sfi.OpenSession())
using (var t = s.BeginTransaction())
{
var person = new Person(age: 20)
{
CardInfo = new("card1", "card2")
};
s.Save(person);
t.Commit();
s.Flush();
personId = person.Id;
}

using (var s = Sfi.OpenSession())
using (var t = s.BeginTransaction())
{
var restored = s.Get<Person>(personId);

var oldCardInfo = restored.CardInfo;

Assert.That(oldCardInfo.GetCardsCopy().Contains("card1"));
Assert.That(oldCardInfo.GetCardsCopy().Contains("card2"));

var newCardInfo = new CardInfo("card1", "card2");

Assert.That(oldCardInfo.GetHashCode(), Is.EqualTo(newCardInfo.GetHashCode()));
Assert.That(oldCardInfo.Equals(newCardInfo));

restored.CardInfo = newCardInfo;

// Expected behaviour:
//
// At this point there should be no DML statements because newCardInfo
// is the same as the old one. But NHibernate will generate DELETE
// followed by 2 INSERT into OldCards table.

using (var x = new SqlLogSpy())
{
t.Commit();
Assert.That(x.GetWholeLog(), Is.Empty);
}
}
}
}
}
21 changes: 21 additions & 0 deletions src/NHibernate.Test/NHSpecificTest/GH3539/Mappings.hbm.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping
xmlns="urn:nhibernate-mapping-2.2"
assembly="NHibernate.Test"
namespace="NHibernate.Test.NHSpecificTest.GH3539">

<class name="Person" table="People">
<id name="_id" type="int" column="ID" access="field">
<generator class="increment"/>
</id>
<property name="_age" type="int" access="field"/>

<component name="_cardInfo" access="field">
<set name="_oldCards" table="OldCards" cascade="all" access="field" >
<key column="PersonId" />
<element column="Card" type="String" />
</set>
</component>
</class>

</hibernate-mapping>
35 changes: 35 additions & 0 deletions src/NHibernate.Test/NHSpecificTest/GH3539/Person.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
namespace NHibernate.Test.NHSpecificTest.GH3539
{
public class Person
{
private int _id;
private int _age;
private CardInfo _cardInfo;

protected Person() { }

public Person(int age)
{
_cardInfo = new();
_age = age;
}

public virtual int Id
{
get { return _id; }
set { _id = value; }
}

public virtual int Age
{
get { return _age; }
set { _age = value; }
}

public virtual CardInfo CardInfo
{
get { return _cardInfo; }
set { _cardInfo = value; }
}
}
}