Skip to content

Improve exception for query on delayed id #3043

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 5 commits into from
Apr 19, 2022
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
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
//------------------------------------------------------------------------------


using System.Linq;
using NHibernate.Cfg;
using NHibernate.Exceptions;
using NUnit.Framework;

namespace NHibernate.Test.Generatedkeys.Identity
Expand Down Expand Up @@ -38,17 +40,238 @@ protected override void Configure(Configuration configuration)
configuration.SetProperty(Environment.GenerateStatistics, "true");
}

protected override void OnTearDown()
{
using (var s = OpenSession())
using (var t = s.BeginTransaction())
{
s.CreateQuery("delete from MyChild").ExecuteUpdate();
s.CreateQuery("delete from MySibling").ExecuteUpdate();
s.CreateQuery("delete from System.Object").ExecuteUpdate();
t.Commit();
s.Close();
}
}

[Test]
public async Task IdentityColumnGeneratedIdsAsync()
{
using (var s = OpenSession())
using (var t = s.BeginTransaction())
{
MyEntity myEntity = new MyEntity("test");
long id = (long) await (s.SaveAsync(myEntity));
Assert.IsNotNull(id, "identity column did not force immediate insert");
Assert.AreEqual(id, myEntity.Id);
await (s.DeleteAsync(myEntity));
var entity1 = new MyEntity("test");
var id1 = (long) await (s.SaveAsync(entity1));
var entity2 = new MyEntity("test2");
var id2 = (long) await (s.SaveAsync(entity2));
// As 0 may be a valid identity value, we check for returned ids being not the same when saving two entities.
Assert.That(id1, Is.Not.EqualTo(id2), "identity column did not force immediate insert");
Assert.That(id1, Is.EqualTo(entity1.Id));
Assert.That(id2, Is.EqualTo(entity2.Id));
await (t.CommitAsync());
s.Close();
}
}

[Test]
public async Task PersistOutsideTransactionAsync()
{
var myEntity1 = new MyEntity("test-save");
var myEntity2 = new MyEntity("test-persist");
using (var s = OpenSession())
{
// first test save() which should force an immediate insert...
var initialInsertCount = Sfi.Statistics.EntityInsertCount;
var id = (long) await (s.SaveAsync(myEntity1));
Assert.That(
Sfi.Statistics.EntityInsertCount,
Is.GreaterThan(initialInsertCount),
"identity column did not force immediate insert");
Assert.That(id, Is.EqualTo(myEntity1.Id));

// next test persist() which should cause a delayed insert...
initialInsertCount = Sfi.Statistics.EntityInsertCount;
await (s.PersistAsync(myEntity2));
Assert.AreEqual(
initialInsertCount,
Sfi.Statistics.EntityInsertCount,
"persist on identity column not delayed");
Assert.AreEqual(0, myEntity2.Id);

// an explicit flush should cause execution of the delayed insertion
await (s.FlushAsync());
Assert.AreEqual(
initialInsertCount + 1,
Sfi.Statistics.EntityInsertCount,
"delayed persist insert not executed on flush");
s.Close();
}

using (var s = OpenSession())
using (var t = s.BeginTransaction())
{
await (s.DeleteAsync(myEntity1));
await (s.DeleteAsync(myEntity2));
await (t.CommitAsync());
s.Close();
}
}

[Test]
public async Task PersistOutsideTransactionCascadedToNonInverseCollectionAsync()
{
long initialInsertCount = Sfi.Statistics.EntityInsertCount;
using (var s = OpenSession())
{
MyEntity myEntity = new MyEntity("test-persist");
myEntity.NonInverseChildren.Add(new MyChild("test-child-persist-non-inverse"));
await (s.PersistAsync(myEntity));
Assert.AreEqual(
initialInsertCount,
Sfi.Statistics.EntityInsertCount,
"persist on identity column not delayed");
Assert.AreEqual(0, myEntity.Id);
await (s.FlushAsync());
Assert.AreEqual(
initialInsertCount + 2,
Sfi.Statistics.EntityInsertCount,
"delayed persist insert not executed on flush");
s.Close();
}

using (var s = OpenSession())
using (var t = s.BeginTransaction())
{
await (s.DeleteAsync("from MyChild"));
await (s.DeleteAsync("from MyEntity"));
await (t.CommitAsync());
s.Close();
}
}

[Test]
public async Task PersistOutsideTransactionCascadedToInverseCollectionAsync()
{
long initialInsertCount = Sfi.Statistics.EntityInsertCount;
using (var s = OpenSession())
{
MyEntity myEntity2 = new MyEntity("test-persist-2");
MyChild child = new MyChild("test-child-persist-inverse");
myEntity2.InverseChildren.Add(child);
child.InverseParent = myEntity2;
await (s.PersistAsync(myEntity2));
Assert.AreEqual(
initialInsertCount,
Sfi.Statistics.EntityInsertCount,
"persist on identity column not delayed");
Assert.AreEqual(0, myEntity2.Id);
await (s.FlushAsync());
Assert.AreEqual(
initialInsertCount + 2,
Sfi.Statistics.EntityInsertCount,
"delayed persist insert not executed on flush");
s.Close();
}

using (var s = OpenSession())
using (var t = s.BeginTransaction())
{
await (s.DeleteAsync("from MyChild"));
await (s.DeleteAsync("from MyEntity"));
await (t.CommitAsync());
s.Close();
}
}

[Test]
public async Task PersistOutsideTransactionCascadedToManyToOneAsync()
{
long initialInsertCount = Sfi.Statistics.EntityInsertCount;
using (var s = OpenSession())
{
MyEntity myEntity = new MyEntity("test-persist");
myEntity.Sibling = new MySibling("test-persist-sibling-out");
await (s.PersistAsync(myEntity));
Assert.AreEqual(
initialInsertCount,
Sfi.Statistics.EntityInsertCount,
"persist on identity column not delayed");
Assert.AreEqual(0, myEntity.Id);
await (s.FlushAsync());
Assert.AreEqual(
initialInsertCount + 2,
Sfi.Statistics.EntityInsertCount,
"delayed persist insert not executed on flush");
s.Close();
}

using (var s = OpenSession())
using (var t = s.BeginTransaction())
{
await (s.DeleteAsync("from MyEntity"));
await (s.DeleteAsync("from MySibling"));
await (t.CommitAsync());
s.Close();
}
}

[Test]
public async Task PersistOutsideTransactionCascadedFromManyToOneAsync()
{
long initialInsertCount = Sfi.Statistics.EntityInsertCount;
using (var s = OpenSession())
{
MyEntity myEntity2 = new MyEntity("test-persist-2");
MySibling sibling = new MySibling("test-persist-sibling-in");
sibling.Entity = myEntity2;
await (s.PersistAsync(sibling));
Assert.AreEqual(
initialInsertCount,
Sfi.Statistics.EntityInsertCount,
"persist on identity column not delayed");
Assert.AreEqual(0, myEntity2.Id);
await (s.FlushAsync());
Assert.AreEqual(
initialInsertCount + 2,
Sfi.Statistics.EntityInsertCount,
"delayed persist insert not executed on flush");
s.Close();
}

using (var s = OpenSession())
using (var t = s.BeginTransaction())
{
await (s.DeleteAsync("from MySibling"));
await (s.DeleteAsync("from MyEntity"));
await (t.CommitAsync());
s.Close();
}
}

[Test]
public async Task QueryOnPersistedEntityAsync([Values(FlushMode.Auto, FlushMode.Commit)] FlushMode flushMode)
{
var myEntity = new MyEntity("test-persist");
using (var s = OpenSession())
using (var t = s.BeginTransaction())
{
s.FlushMode = flushMode;

var initialInsertCount = Sfi.Statistics.EntityInsertCount;
await (s.PersistAsync(myEntity));
Assert.That(Sfi.Statistics.EntityInsertCount, Is.EqualTo(initialInsertCount),
"persist on identity column not delayed");
Assert.That(myEntity.Id, Is.Zero);

var query = s.Query<MyChild>().Where(c => c.InverseParent == myEntity);
switch (flushMode)
{
case FlushMode.Auto:
Assert.That(query.ToList, Throws.Nothing);
break;
case FlushMode.Commit:
Assert.That(query.ToList, Throws.Exception.TypeOf(typeof(UnresolvableObjectException)));
break;
}
await (t.CommitAsync());
s.Close();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Linq;
using NHibernate.Cfg;
using NHibernate.Exceptions;
using NUnit.Framework;

namespace NHibernate.Test.Generatedkeys.Identity
Expand Down Expand Up @@ -27,36 +29,56 @@ protected override void Configure(Configuration configuration)
configuration.SetProperty(Environment.GenerateStatistics, "true");
}

protected override void OnTearDown()
{
using (var s = OpenSession())
using (var t = s.BeginTransaction())
{
s.CreateQuery("delete from MyChild").ExecuteUpdate();
s.CreateQuery("delete from MySibling").ExecuteUpdate();
s.CreateQuery("delete from System.Object").ExecuteUpdate();
t.Commit();
s.Close();
}
}

[Test]
public void IdentityColumnGeneratedIds()
{
using (var s = OpenSession())
using (var t = s.BeginTransaction())
{
MyEntity myEntity = new MyEntity("test");
long id = (long) s.Save(myEntity);
Assert.IsNotNull(id, "identity column did not force immediate insert");
Assert.AreEqual(id, myEntity.Id);
s.Delete(myEntity);
var entity1 = new MyEntity("test");
var id1 = (long) s.Save(entity1);
var entity2 = new MyEntity("test2");
var id2 = (long) s.Save(entity2);
// As 0 may be a valid identity value, we check for returned ids being not the same when saving two entities.
Assert.That(id1, Is.Not.EqualTo(id2), "identity column did not force immediate insert");
Assert.That(id1, Is.EqualTo(entity1.Id));
Assert.That(id2, Is.EqualTo(entity2.Id));
t.Commit();
s.Close();
}
}

[Test, Ignore("Not supported yet.")]
[Test]
public void PersistOutsideTransaction()
{
var myEntity1 = new MyEntity("test-save");
var myEntity2 = new MyEntity("test-persist");
using (var s = OpenSession())
{
// first test save() which should force an immediate insert...
long id = (long) s.Save(myEntity1);
Assert.IsNotNull(id, "identity column did not force immediate insert");
Assert.AreEqual(id, myEntity1.Id);
var initialInsertCount = Sfi.Statistics.EntityInsertCount;
var id = (long) s.Save(myEntity1);
Assert.That(
Sfi.Statistics.EntityInsertCount,
Is.GreaterThan(initialInsertCount),
"identity column did not force immediate insert");
Assert.That(id, Is.EqualTo(myEntity1.Id));

// next test persist() which should cause a delayed insert...
long initialInsertCount = Sfi.Statistics.EntityInsertCount;
initialInsertCount = Sfi.Statistics.EntityInsertCount;
s.Persist(myEntity2);
Assert.AreEqual(
initialInsertCount,
Expand All @@ -83,7 +105,7 @@ public void PersistOutsideTransaction()
}
}

[Test, Ignore("Not supported yet.")]
[Test]
public void PersistOutsideTransactionCascadedToNonInverseCollection()
{
long initialInsertCount = Sfi.Statistics.EntityInsertCount;
Expand Down Expand Up @@ -115,7 +137,7 @@ public void PersistOutsideTransactionCascadedToNonInverseCollection()
}
}

[Test, Ignore("Not supported yet.")]
[Test]
public void PersistOutsideTransactionCascadedToInverseCollection()
{
long initialInsertCount = Sfi.Statistics.EntityInsertCount;
Expand Down Expand Up @@ -149,7 +171,7 @@ public void PersistOutsideTransactionCascadedToInverseCollection()
}
}

[Test, Ignore("Not supported yet.")]
[Test]
public void PersistOutsideTransactionCascadedToManyToOne()
{
long initialInsertCount = Sfi.Statistics.EntityInsertCount;
Expand Down Expand Up @@ -181,7 +203,7 @@ public void PersistOutsideTransactionCascadedToManyToOne()
}
}

[Test, Ignore("Not supported yet.")]
[Test]
public void PersistOutsideTransactionCascadedFromManyToOne()
{
long initialInsertCount = Sfi.Statistics.EntityInsertCount;
Expand Down Expand Up @@ -213,5 +235,35 @@ public void PersistOutsideTransactionCascadedFromManyToOne()
s.Close();
}
}

[Test]
public void QueryOnPersistedEntity([Values(FlushMode.Auto, FlushMode.Commit)] FlushMode flushMode)
{
var myEntity = new MyEntity("test-persist");
using (var s = OpenSession())
using (var t = s.BeginTransaction())
{
s.FlushMode = flushMode;

var initialInsertCount = Sfi.Statistics.EntityInsertCount;
s.Persist(myEntity);
Assert.That(Sfi.Statistics.EntityInsertCount, Is.EqualTo(initialInsertCount),
"persist on identity column not delayed");
Assert.That(myEntity.Id, Is.Zero);

var query = s.Query<MyChild>().Where(c => c.InverseParent == myEntity);
switch (flushMode)
{
case FlushMode.Auto:
Assert.That(query.ToList, Throws.Nothing);
break;
case FlushMode.Commit:
Assert.That(query.ToList, Throws.Exception.TypeOf(typeof(UnresolvableObjectException)));
break;
}
t.Commit();
s.Close();
}
}
}
}
Loading