diff --git a/src/AsyncGenerator.yml b/src/AsyncGenerator.yml
index 382d07d44c9..f9f2f990ce3 100644
--- a/src/AsyncGenerator.yml
+++ b/src/AsyncGenerator.yml
@@ -26,6 +26,9 @@
- conversion: Ignore
name: InitializeLazyPropertiesFromCache
containingTypeName: AbstractEntityPersister
+ - conversion: Ignore
+ name: GetElementOwnerPropertyValue
+ containingTypeName: AbstractCollectionPersister
- conversion: Ignore
name: Invoke
containingTypeName: BasicLazyInitializer
diff --git a/src/NHibernate.Test/Async/CollectionCompositeKey/Fixture.cs b/src/NHibernate.Test/Async/CollectionCompositeKey/Fixture.cs
new file mode 100644
index 00000000000..7641c06c173
--- /dev/null
+++ b/src/NHibernate.Test/Async/CollectionCompositeKey/Fixture.cs
@@ -0,0 +1,217 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by AsyncGenerator.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+
+using System;
+using System.Collections.Generic;
+using NHibernate.Event;
+using NHibernate.Persister.Collection;
+using NUnit.Framework;
+using NUnit.Framework.Constraints;
+
+namespace NHibernate.Test.CollectionCompositeKey
+{
+ using System.Threading.Tasks;
+ using System.Threading;
+ [TestFixture]
+ public class FixtureAsync : TestCase
+ {
+ private readonly Parent _parentId = new Parent("1", 1);
+ private int _currentChildId = 1;
+ private int _currentGrandChildId = 1;
+
+ protected override string[] Mappings => new [] { "CollectionCompositeKey.CollectionOwner.hbm.xml" };
+
+ protected override string MappingsAssembly => "NHibernate.Test";
+
+ protected override string CacheConcurrencyStrategy => null;
+
+ protected override void OnSetUp()
+ {
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ var parent = CreateParent(_parentId.Code, _parentId.Number);
+
+ s.Save(parent);
+ t.Commit();
+ }
+ }
+
+ protected override void OnTearDown()
+ {
+ using (var session = OpenSession())
+ using (var tx = session.BeginTransaction())
+ {
+ session.Delete("from GrandChild");
+ session.Delete("from Child");
+ session.Delete("from Parent");
+ tx.Commit();
+ }
+ base.OnTearDown();
+ }
+
+ [TestCase(nameof(Parent.Children), true, true)]
+ [TestCase(nameof(Parent.ChildrenByForeignKeys), true, false)]
+ [TestCase(nameof(Parent.ChildrenByComponent), true, true)]
+ [TestCase(nameof(Parent.ChildrenByComponentForeignKeys), true, false)]
+ [TestCase(nameof(Parent.ChildrenNoProperties), false, false)]
+ [TestCase(nameof(Parent.ChildrenByUniqueKey), true, true)]
+ [TestCase(nameof(Parent.ChildrenByUniqueKeyNoManyToOne), true, false)]
+ [TestCase(nameof(Parent.ChildrenByCompositeUniqueKey), true, true)]
+ [TestCase(nameof(Parent.ChildrenByCompositeUniqueKeyNoManyToOne), true, false)]
+ public Task TestGetElementOwnerForChildCollectionsAsync(string collectionProperty, bool propertyExists, bool hasManyToOne, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return TestGetElementOwnerForChildCollectionsAsync(collectionProperty, propertyExists, hasManyToOne, (parent, child) => child.Id, cancellationToken);
+ }
+
+ [TestCase(nameof(Parent.GrandChildren), true, true)]
+ public Task TestGetElementOwnerForGrandChildCollectionsAsync(string collectionProperty, bool propertyExists, bool hasManyToOne, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return TestGetElementOwnerForChildCollectionsAsync(collectionProperty, propertyExists, hasManyToOne, GetGrandChildId, cancellationToken);
+ }
+
+ private static object GetGrandChildId(Parent parent, GrandChild child)
+ {
+ if (parent == null)
+ {
+ return null; // Not supported
+ }
+
+ child.GrandParent = parent;
+ return child;
+ }
+
+ private async Task TestGetElementOwnerForChildCollectionsAsync(string collectionProperty, bool propertyExists, bool hasManyToOne, Func getChildId, CancellationToken cancellationToken = default(CancellationToken))
+ where TChild : class
+ {
+ var persister = Sfi.GetEntityPersister(typeof(Parent).FullName);
+ var collPersister = GetCollectionPersister(collectionProperty);
+ TChild firstChild = null;
+
+ var propertyIndex = -1;
+ for (var i = 0; i < persister.PropertyNames.Length; i++)
+ {
+ if (persister.PropertyNames[i] == collectionProperty)
+ {
+ propertyIndex = i;
+ break;
+ }
+ }
+
+ Assert.That(propertyIndex, Is.Not.EqualTo(-1));
+
+ // Test when collection is loaded
+ using (var s = (IEventSource) OpenSession())
+ using (var tx = s.BeginTransaction())
+ {
+ var parent = await (s.GetAsync(_parentId, cancellationToken));
+ Assert.That(parent, Is.Not.Null);
+
+ var collection = (IList) persister.GetPropertyValue(parent, propertyIndex);
+ foreach (var child in collection)
+ {
+ if (firstChild == null)
+ {
+ firstChild = child;
+ }
+
+ Assert.That(collPersister.GetElementOwner(child, s), propertyExists ? Is.EqualTo(parent) : (IResolveConstraint) Is.Null);
+ }
+
+ await (tx.CommitAsync(cancellationToken));
+ }
+
+ Assert.That(firstChild, Is.Not.Null);
+
+ // Test when collection is not loaded
+ using (var s = (IEventSource) OpenSession())
+ using (var tx = s.BeginTransaction())
+ {
+ var parent = await (s.GetAsync(_parentId, cancellationToken));
+ var child = await (s.GetAsync(getChildId(parent, firstChild), cancellationToken));
+ Assert.That(parent, Is.Not.Null);
+ Assert.That(child, Is.Not.Null);
+
+ Assert.That(collPersister.GetElementOwner(child, s), propertyExists ? Is.EqualTo(parent) : (IResolveConstraint) Is.Null);
+
+ await (tx.CommitAsync(cancellationToken));
+ }
+
+ // Test when only the child is loaded
+ using (var s = (IEventSource) OpenSession())
+ using (var tx = s.BeginTransaction())
+ {
+ var id = getChildId(null, firstChild);
+ if (id != null)
+ {
+ var child = await (s.GetAsync(id, cancellationToken));
+ Assert.That(child, Is.Not.Null);
+
+ Assert.That(collPersister.GetElementOwner(child, s), hasManyToOne ? Is.InstanceOf() : (IResolveConstraint) Is.Null);
+ }
+
+ await (tx.CommitAsync(cancellationToken));
+ }
+
+ // Test transient
+ using (var s = (IEventSource) OpenSession())
+ using (var tx = s.BeginTransaction())
+ {
+ var parent = CreateParent("2", 2);
+ var collection = (IList) persister.GetPropertyValue(parent, propertyIndex);
+
+ foreach (var child in collection)
+ {
+ Assert.That(collPersister.GetElementOwner(child, s), hasManyToOne ? Is.EqualTo(parent) : (IResolveConstraint) Is.Null);
+ }
+
+ await (tx.CommitAsync(cancellationToken));
+ }
+ }
+
+ private AbstractCollectionPersister GetCollectionPersister(string collectionProperty)
+ {
+ return (AbstractCollectionPersister) Sfi.GetCollectionPersister($"{typeof(Parent).FullName}.{collectionProperty}");
+ }
+
+ private Parent CreateParent(string code, int number)
+ {
+ var parent = new Parent(code, number)
+ {
+ Name = $"parent{number}",
+ ReferenceCode = code,
+ ReferenceNumber = number
+ };
+
+ parent.Children.Add(new Child(_currentChildId++, "child", parent) { Parent = parent });
+ parent.ChildrenByForeignKeys.Add(new Child(_currentChildId++, "childFk", parent) { ParentNumber = parent.Number, ParentCode = parent.Code });
+ parent.ChildrenByComponent.Add(new Child(_currentChildId++, "childCo", parent) { Component = new ChildComponent { Parent = parent } });
+ parent.ChildrenByComponentForeignKeys.Add(
+ new Child(_currentChildId++, "childCoFk", parent)
+ {
+ Component = new ChildComponent { ParentNumber = parent.Number, ParentCode = parent.Code }
+ });
+ parent.ChildrenNoProperties.Add(new Child(_currentChildId++, "childNp", parent));
+ parent.ChildrenByUniqueKey.Add(new Child(_currentChildId++, "childUk", parent) { ParentByName = parent });
+ parent.ChildrenByUniqueKeyNoManyToOne.Add(new Child(_currentChildId++, "childUkFk", parent) { ParentName = parent.Name });
+ parent.ChildrenByCompositeUniqueKey.Add(new Child(_currentChildId++, "childCoUk", parent) { ParentByReference = parent });
+ parent.ChildrenByCompositeUniqueKeyNoManyToOne.Add(
+ new Child(_currentChildId++, "childCoUkFk", parent)
+ {
+ ParentReferenceCode = parent.ReferenceCode,
+ ParentReferenceNumber = parent.ReferenceNumber
+ });
+
+ parent.GrandChildren.Add(new GrandChild(_currentGrandChildId, "grandChild", parent));
+
+ return parent;
+ }
+ }
+}
diff --git a/src/NHibernate.Test/Async/Extralazy/ExtraLazyFixture.cs b/src/NHibernate.Test/Async/Extralazy/ExtraLazyFixture.cs
index 4dd7e85fced..d338404834a 100644
--- a/src/NHibernate.Test/Async/Extralazy/ExtraLazyFixture.cs
+++ b/src/NHibernate.Test/Async/Extralazy/ExtraLazyFixture.cs
@@ -8,14 +8,19 @@
//------------------------------------------------------------------------------
+using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
+using NHibernate.Cfg;
+using NHibernate.Id;
using NUnit.Framework;
+using NUnit.Framework.Constraints;
namespace NHibernate.Test.Extralazy
{
using System.Threading.Tasks;
+ using System.Threading;
[TestFixture]
public class ExtraLazyFixtureAsync : TestCase
{
@@ -34,13 +39,2876 @@ protected override string CacheConcurrencyStrategy
get { return null; }
}
+ protected override void Configure(Configuration configuration)
+ {
+ configuration.SetProperty(Cfg.Environment.GenerateStatistics, "true");
+ }
+
protected override void OnTearDown()
{
using (var s = OpenSession())
using (var t = s.BeginTransaction())
{
- s.Delete("from System.Object");
- t.Commit();
+ s.Delete("from System.Object");
+ t.Commit();
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public async Task MapAddChildSaveChangeParentAsync(bool initialize, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ User gavin;
+ User turin;
+ var gavinItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ turin = new User("turin", "tiger");
+ await (s.PersistAsync(gavin, cancellationToken));
+ await (s.PersistAsync(turin, cancellationToken));
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new UserSetting($"g{i}", $"data{i}", gavin);
+ gavinItems.Add(item);
+ gavin.Settings.Add(item.Name, item);
+
+ item = new UserSetting($"t{i}", $"data{i}", turin);
+ turin.Settings.Add(item.Name, item);
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ turin = await (s.GetAsync("turin", cancellationToken));
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Settings.Count, Is.EqualTo(5));
+ Assert.That(turin.Settings.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+ Assert.That(NHibernateUtil.IsInitialized(turin.Settings), Is.False);
+
+ // Save companies and then add them to the collection
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ var item = new UserSetting($"c{i}", $"data{i}", gavin);
+ await (s.SaveAsync(item, cancellationToken));
+ gavinItems.Add(item);
+ }
+
+ for (var i = 5; i < 10; i++)
+ {
+ gavin.Settings.Add(gavinItems[i].Name, gavinItems[i]);
+ }
+
+ Assert.That(gavin.Settings.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Add companies to the collection and then save them
+ Sfi.Statistics.Clear();
+ for (var i = 10; i < 15; i++)
+ {
+ var item = new UserSetting($"c{i}", $"data{i}", gavin);
+ gavin.Settings.Add(item.Name, item);
+ gavinItems.Add(item);
+ await (s.SaveAsync(item, cancellationToken));
+ }
+
+ Assert.That(gavin.Settings.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Remove added items from the collection and add them to a different parent
+ foreach (var item in gavinItems.Skip(5).Take(5))
+ {
+ gavin.Settings.Remove(item.Name);
+
+ item.Owner = turin;
+ turin.Settings.Add(item.Name, item);
+ }
+
+ // Remove added items from the collection
+ for (var i = 10; i < 15; i++)
+ {
+ var item = gavinItems[i];
+ gavin.Settings.Remove(item.Name);
+ // When identity is used for the primary key the item will be already inserted in the database,
+ // so the RemoveAt method will mark it as an orphan which will be deleted on flush.
+ // The same would work for an initialized collection as the collection snapshot would contain the item.
+ // When dealing with an id generator that supports a delayed insert, we have to trigger a delete
+ // for the item as it is currently scheduled for insertion.
+ if (IsNativeIdentityGenerator)
+ {
+ if (i % 2 != 0)
+ {
+ item.Owner = null;
+ }
+ }
+ else
+ {
+ await (s.DeleteAsync(item, cancellationToken));
+ }
+ }
+
+ Assert.That(gavin.Settings.Count, Is.EqualTo(5));
+ Assert.That(turin.Settings.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+ Assert.That(NHibernateUtil.IsInitialized(turin.Settings), Is.False);
+
+ if (initialize)
+ {
+ using (var e = gavin.Settings.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+ using (var e = turin.Settings.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.True);
+ Assert.That(NHibernateUtil.IsInitialized(turin.Settings), Is.True);
+ Assert.That(gavin.Settings.Count, Is.EqualTo(5));
+ Assert.That(turin.Settings.Count, Is.EqualTo(10));
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ turin = await (s.GetAsync("turin", cancellationToken));
+ Assert.That(gavin.Settings.Count, Is.EqualTo(5));
+ Assert.That(turin.Settings.Count, Is.EqualTo(10));
+
+ await (t.CommitAsync(cancellationToken));
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public async Task ListInsertChildSaveChangeParentAsync(bool initialize, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ User gavin;
+ User turin;
+ var gavinItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ turin = new User("turin", "tiger");
+ await (s.PersistAsync(gavin, cancellationToken));
+ await (s.PersistAsync(turin, cancellationToken));
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new Company($"g{i}", i, gavin);
+ gavinItems.Add(item);
+ gavin.Companies.Add(item);
+
+ item = new Company($"t{i}", i, turin);
+ turin.Companies.Add(item);
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ turin = await (s.GetAsync("turin", cancellationToken));
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(turin.Companies.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+ Assert.That(NHibernateUtil.IsInitialized(turin.Companies), Is.False);
+
+ // Save companies and then add them to the collection
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ await (s.SaveAsync(item, cancellationToken));
+ gavinItems.Add(item);
+ }
+
+ for (var i = 5; i < 10; i++)
+ {
+ if (i % 2 != 0)
+ {
+ gavin.Companies.Insert(i, gavinItems[i]);
+ }
+ else
+ {
+ gavin.Companies.Add(gavinItems[i]);
+ }
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Add companies to the collection and then save them
+ Sfi.Statistics.Clear();
+ for (var i = 10; i < 15; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ if (i % 2 != 0)
+ {
+ gavin.Companies.Insert(i, item);
+ }
+ else
+ {
+ gavin.Companies.Add(item);
+ }
+
+ gavinItems.Add(item);
+ await (s.SaveAsync(item, cancellationToken));
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Remove added items from the collection and add them to a different parent
+ foreach (var item in gavinItems.Skip(5).Take(5))
+ {
+ gavin.Companies.RemoveAt(5);
+
+ item.Owner = turin;
+ turin.Companies.Insert(item.ListIndex, item);
+ }
+
+ // Remove added items from the collection
+ for (var i = 10; i < 15; i++)
+ {
+ var item = gavinItems[i];
+ gavin.Companies.RemoveAt(5);
+ // When identity is used for the primary key the item will be already inserted in the database,
+ // so the RemoveAt method will mark it as an orphan which will be deleted on flush.
+ // The same would work for an initialized collection as the collection snapshot would contain the item.
+ // When dealing with an id generator that supports a delayed insert, we have to trigger a delete
+ // for the item as it is currently scheduled for insertion.
+ if (IsNativeIdentityGenerator)
+ {
+ if (i % 2 != 0)
+ {
+ item.Owner = null;
+ }
+ }
+ else
+ {
+ await (s.DeleteAsync(item, cancellationToken));
+ }
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(turin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+ Assert.That(NHibernateUtil.IsInitialized(turin.Companies), Is.False);
+
+ if (initialize)
+ {
+ using (var e = gavin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+ using (var e = turin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+ Assert.That(NHibernateUtil.IsInitialized(turin.Companies), Is.True);
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(turin.Companies.Count, Is.EqualTo(10));
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ turin = await (s.GetAsync("turin", cancellationToken));
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(turin.Companies.Count, Is.EqualTo(10));
+
+ await (t.CommitAsync(cancellationToken));
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public async Task ListClearChildSaveChangeParentAsync(bool initialize, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ User gavin;
+ User turin;
+ var gavinItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ turin = new User("turin", "tiger");
+ await (s.PersistAsync(gavin, cancellationToken));
+ await (s.PersistAsync(turin, cancellationToken));
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new CreditCard($"g{i}", i, gavin);
+ gavin.CreditCards.Add(item);
+
+ item = new CreditCard($"t{i}", i, turin);
+ turin.CreditCards.Add(item);
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ turin = await (s.GetAsync("turin", cancellationToken));
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.CreditCards.Count, Is.EqualTo(5));
+ Assert.That(turin.CreditCards.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.CreditCards), Is.False);
+ Assert.That(NHibernateUtil.IsInitialized(turin.CreditCards), Is.False);
+
+ Sfi.Statistics.Clear();
+ gavin.CreditCards.Clear();
+ turin.CreditCards.Clear();
+ Assert.That(gavin.CreditCards.Count, Is.EqualTo(0));
+ Assert.That(turin.CreditCards.Count, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.CreditCards), Is.False);
+ Assert.That(NHibernateUtil.IsInitialized(turin.CreditCards), Is.False);
+
+ // Save credit cards and then add them to the collection
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new CreditCard($"c2{i}", i, gavin);
+ await (s.SaveAsync(item, cancellationToken));
+ gavinItems.Add(item);
+ }
+
+ for (var i = 0; i < 5; i++)
+ {
+ gavin.CreditCards.Add(gavinItems[i]);
+ }
+
+ Assert.That(gavin.CreditCards.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.CreditCards), Is.False);
+
+ // Add credit cards to the collection and then save them
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ var item = new CreditCard($"c2{i}", i, gavin);
+ Assert.That(((IList) gavin.CreditCards).Add(item), Is.EqualTo(i));
+ gavinItems.Add(item);
+ await (s.SaveAsync(item, cancellationToken));
+ }
+
+ Assert.That(gavin.CreditCards.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.CreditCards), Is.False);
+
+ // Remove added items from the collection and add them to a different parent
+ foreach (var item in gavinItems.Take(5))
+ {
+ gavin.CreditCards.Remove(item);
+
+ item.Owner = turin;
+ item.ListIndex += 5;
+ turin.CreditCards.Add(item);
+ }
+
+ Assert.That(gavin.CreditCards.Count, Is.EqualTo(5));
+ Assert.That(turin.CreditCards.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.CreditCards), Is.False);
+ Assert.That(NHibernateUtil.IsInitialized(turin.CreditCards), Is.False);
+
+ if (initialize)
+ {
+ using (var e = gavin.CreditCards.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+ using (var e = turin.CreditCards.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.CreditCards), Is.True);
+ Assert.That(NHibernateUtil.IsInitialized(turin.CreditCards), Is.True);
+ Assert.That(gavin.CreditCards.Count, Is.EqualTo(5));
+ Assert.That(turin.CreditCards.Count, Is.EqualTo(5));
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ turin = await (s.GetAsync("turin", cancellationToken));
+ Assert.That(gavin.CreditCards.Count, Is.EqualTo(10));
+ Assert.That(turin.CreditCards.Count, Is.EqualTo(10));
+
+ await (t.CommitAsync(cancellationToken));
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public async Task ListAddChildSaveChangeParentAsync(bool initialize, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ User gavin;
+ User turin;
+ var gavinItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ turin = new User("turin", "tiger");
+ await (s.PersistAsync(gavin, cancellationToken));
+ await (s.PersistAsync(turin, cancellationToken));
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new Company($"g{i}", i, gavin);
+ gavinItems.Add(item);
+ gavin.Companies.Add(item);
+
+ item = new Company($"t{i}", i, turin);
+ turin.Companies.Add(item);
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ turin = await (s.GetAsync("turin", cancellationToken));
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(turin.Companies.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+ Assert.That(NHibernateUtil.IsInitialized(turin.Companies), Is.False);
+
+ // Save companies and then add them to the collection
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ await (s.SaveAsync(item, cancellationToken));
+ gavinItems.Add(item);
+ }
+
+ for (var i = 5; i < 10; i++)
+ {
+ gavin.Companies.Add(gavinItems[i]);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Add companies to the collection and then save them
+ Sfi.Statistics.Clear();
+ for (var i = 10; i < 15; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ Assert.That(((IList) gavin.Companies).Add(item), Is.EqualTo(i));
+ gavinItems.Add(item);
+ await (s.SaveAsync(item, cancellationToken));
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Remove added items from the collection and add them to a different parent
+ foreach (var item in gavinItems.Skip(5).Take(5))
+ {
+ gavin.Companies.Remove(item);
+
+ item.Owner = turin;
+ turin.Companies.Add(item);
+ }
+
+ // Remove added items from the collection
+ for (var i = 10; i < 15; i++)
+ {
+ var item = gavinItems[i];
+ gavin.Companies.Remove(item);
+ // When identity is used for the primary key the item will be already inserted in the database,
+ // so the RemoveAt method will mark it as an orphan which will be deleted on flush.
+ // The same would work for an initialized collection as the collection snapshot would contain the item.
+ // When dealing with an id generator that supports a delayed insert, we have to trigger a delete
+ // for the item as it is currently scheduled for insertion.
+ if (IsNativeIdentityGenerator)
+ {
+ if (i % 2 != 0)
+ {
+ item.Owner = null;
+ }
+ }
+ else
+ {
+ await (s.DeleteAsync(item, cancellationToken));
+ }
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(turin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+ Assert.That(NHibernateUtil.IsInitialized(turin.Companies), Is.False);
+
+ if (initialize)
+ {
+ using (var e = gavin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+ using (var e = turin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+ Assert.That(NHibernateUtil.IsInitialized(turin.Companies), Is.True);
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(turin.Companies.Count, Is.EqualTo(10));
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ turin = await (s.GetAsync("turin", cancellationToken));
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(turin.Companies.Count, Is.EqualTo(10));
+
+ await (t.CommitAsync(cancellationToken));
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public async Task ListAddChildSaveAsync(bool initialize, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ User gavin;
+ var gavinItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ await (s.PersistAsync(gavin, cancellationToken));
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new Company($"g{i}", i, gavin);
+ gavinItems.Add(item);
+ gavin.Companies.Add(item);
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+
+ Sfi.Statistics.Clear();
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Save companies and then add them to the collection
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ await (s.SaveAsync(item, cancellationToken));
+ gavinItems.Add(item);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(IsNativeIdentityGenerator ? 10 : 5));
+
+ for (var i = 5; i < 10; i++)
+ {
+ gavin.Companies.Add(gavinItems[i]);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Add companies to the collection and then save them
+ Sfi.Statistics.Clear();
+ for (var i = 10; i < 15; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ Assert.That(((IList) gavinItems).Add(item), Is.EqualTo(i));
+ gavin.Companies.Add(item);
+ await (s.SaveAsync(item, cancellationToken));
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ if (initialize)
+ {
+ using (var e = gavin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ await (t.CommitAsync(cancellationToken));
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public async Task ListAddAsync(bool initialize, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ User gavin;
+ var addedItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ await (s.PersistAsync(gavin, cancellationToken));
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Add(item);
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Test adding companies with ICollection interface
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Add(item);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Test adding companies with IList interface
+ Sfi.Statistics.Clear();
+ for (var i = 10; i < 15; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ Assert.That(((IList)addedItems).Add(item), Is.EqualTo(i));
+ gavin.Companies.Add(item);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+
+ // Check existance of added companies
+ Sfi.Statistics.Clear();
+ foreach (var item in addedItems.Skip(5))
+ {
+ Assert.That(gavin.Companies.Contains(item), Is.True);
+ }
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Check existance of not loaded companies
+ Assert.That(gavin.Companies.Contains(addedItems[0]), Is.True);
+ Assert.That(gavin.Companies.Contains(addedItems[1]), Is.True);
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Check existance of not existing companies
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Companies.Contains(new Company("test1", 15, gavin)), Is.False);
+ Assert.That(gavin.Companies.Contains(new Company("test2", 16, gavin)), Is.False);
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ if (initialize)
+ {
+ using (var e = gavin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ await (t.CommitAsync(cancellationToken));
+ }
+ }
+
+ [TestCase(false, false)]
+ [TestCase(false, true)]
+ [TestCase(true, false)]
+ [TestCase(true, true)]
+ public async Task ListAddDuplicatedAsync(bool initialize, bool flush, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ User gavin;
+ var addedItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ await (s.PersistAsync(gavin, cancellationToken));
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Add(item);
+ gavin.Companies.Add(item);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ // Refresh added items
+ for (var i = 0; i < 5; i++)
+ {
+ addedItems[i] = await (s.GetAsync(addedItems[i].Id, cancellationToken));
+ }
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Readd items
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ gavin.Companies.Add(addedItems[i]);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ if (flush)
+ {
+ await (s.FlushAsync(cancellationToken));
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+ }
+
+ if (initialize)
+ {
+ using (var e = gavin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+ Assert.That(gavin.Companies.Count, Is.EqualTo(flush ? 5 : 10));
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ await (t.CommitAsync(cancellationToken));
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public async Task ListInsertAsync(bool initialize, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ User gavin;
+ var addedItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ await (s.PersistAsync(gavin, cancellationToken));
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Add(item);
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Test inserting companies at the start
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Insert(0, item);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Test inserting companies at the end
+ Sfi.Statistics.Clear();
+ for (var i = 10; i < 15; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Insert(i, item);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Try insert invalid indexes
+ Assert.Throws(() => gavin.Companies.RemoveAt(-1));
+ Assert.Throws(() => gavin.Companies.RemoveAt(20));
+
+ // Check existance of added companies
+ Sfi.Statistics.Clear();
+ foreach (var item in addedItems.Skip(5))
+ {
+ Assert.That(gavin.Companies.Contains(item), Is.True);
+ }
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Check existance of not loaded companies
+ Assert.That(gavin.Companies.Contains(addedItems[0]), Is.True);
+ Assert.That(gavin.Companies.Contains(addedItems[1]), Is.True);
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Check existance of not existing companies
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Companies.Contains(new Company("test1", 15, gavin)), Is.False);
+ Assert.That(gavin.Companies.Contains(new Company("test2", 16, gavin)), Is.False);
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ if (initialize)
+ {
+ using (var e = gavin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ await (t.CommitAsync(cancellationToken));
+ }
+ }
+
+ [TestCase(false, false)]
+ [TestCase(false, true)]
+ [TestCase(true, false)]
+ [TestCase(true, true)]
+ public async Task ListInsertDuplicatedAsync(bool initialize, bool flush, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ User gavin;
+ var addedItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ await (s.PersistAsync(gavin, cancellationToken));
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Insert(i, item);
+ gavin.Companies.Insert(i, item);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ // Refresh added items
+ for (var i = 0; i < 5; i++)
+ {
+ addedItems[i] = await (s.GetAsync(addedItems[i].Id, cancellationToken));
+ }
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Readd items
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ gavin.Companies.Insert(4 - i, addedItems[i]);
+ }
+
+ Assert.That(gavin.Companies[0].ListIndex, Is.EqualTo(4));
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ if (flush)
+ {
+ await (s.FlushAsync(cancellationToken));
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+ }
+
+ if (initialize)
+ {
+ using (var e = gavin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+ Assert.That(gavin.Companies.Count, Is.EqualTo(flush ? 5 : 10));
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ await (t.CommitAsync(cancellationToken));
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public async Task ListRemoveAtAsync(bool initialize, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ User gavin;
+ var addedItems = new List();
+ var finalIndexOrder = new List {0, 1, 2, 6, 8, 9};
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ await (s.PersistAsync(gavin, cancellationToken));
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Add(item);
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ // Refresh added items
+ for (var i = 0; i < 5; i++)
+ {
+ addedItems[i] = await (s.GetAsync(addedItems[i].Id, cancellationToken));
+ }
+
+ // Add transient companies
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Insert(i, item);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Remove transient companies
+ Sfi.Statistics.Clear();
+ gavin.Companies.RemoveAt(5);
+ gavin.Companies.RemoveAt(6);
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(8));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Remove persisted companies
+ Sfi.Statistics.Clear();
+ gavin.Companies.RemoveAt(3);
+ gavin.Companies.RemoveAt(3);
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(6));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Try remove invalid indexes
+ Assert.Throws(() => gavin.Companies.RemoveAt(-1));
+ Assert.Throws(() => gavin.Companies.RemoveAt(8));
+
+ // Check existance of companies
+ Sfi.Statistics.Clear();
+ var removedIndexes = new HashSet {3, 4, 5, 7};
+ for (var i = 0; i < addedItems.Count; i++)
+ {
+ Assert.That(
+ gavin.Companies.Contains(addedItems[i]),
+ removedIndexes.Contains(i) ? Is.False : (IResolveConstraint) Is.True,
+ $"Element at index {i} was {(removedIndexes.Contains(i) ? "not " : "")}removed");
+ }
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(3));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Check existance of not existing companies
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Companies.Contains(new Company("test1", 15, gavin)), Is.False);
+ Assert.That(gavin.Companies.Contains(new Company("test2", 16, gavin)), Is.False);
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ gavin.UpdateCompaniesIndexes();
+
+ if (initialize)
+ {
+ using (var e = gavin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+ Assert.That(gavin.Companies.Count, Is.EqualTo(6));
+ Assert.That(gavin.Companies.Select(o => o.OriginalIndex), Is.EquivalentTo(finalIndexOrder));
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ Assert.That(gavin.Companies.Count, Is.EqualTo(6));
+ Assert.That(gavin.Companies.Select(o => o.OriginalIndex), Is.EquivalentTo(finalIndexOrder));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+
+ await (t.CommitAsync(cancellationToken));
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public async Task ListGetSetAsync(bool initialize, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ User gavin;
+ var addedItems = new List();
+ var finalIndexOrder = new List {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ await (s.PersistAsync(gavin, cancellationToken));
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Add(item);
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ // Refresh added items
+ for (var i = 0; i < 5; i++)
+ {
+ addedItems[i] = await (s.GetAsync(addedItems[i].Id, cancellationToken));
+ }
+
+ // Add transient companies
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Insert(i, item);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Compare all items
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 10; i++)
+ {
+ Assert.That(gavin.Companies[i], Is.EqualTo(addedItems[i]));
+ }
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Try get invalid indexes
+ Assert.Throws(() =>
+ {
+ var item = gavin.Companies[10];
+ });
+ Assert.Throws(() =>
+ {
+ var item = gavin.Companies[-1];
+ });
+
+ // Try set invalid indexes
+ Assert.Throws(() => gavin.Companies[10] = addedItems[0]);
+ Assert.Throws(() => gavin.Companies[-1] = addedItems[0]);
+
+ // Swap transient and persisted indexes
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ var hiIndex = 9 - i;
+ var tmp = gavin.Companies[i];
+ gavin.Companies[i] = gavin.Companies[hiIndex];
+ gavin.Companies[hiIndex] = tmp;
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(10));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Check indexes
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 10; i++)
+ {
+ Assert.That(gavin.Companies[i].ListIndex, Is.EqualTo(finalIndexOrder[i]));
+ }
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ gavin.UpdateCompaniesIndexes();
+
+ if (initialize)
+ {
+ using (var e = gavin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(gavin.Companies.Select(o => o.OriginalIndex), Is.EquivalentTo(finalIndexOrder));
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(gavin.Companies.Select(o => o.OriginalIndex), Is.EquivalentTo(finalIndexOrder));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+
+ await (t.CommitAsync(cancellationToken));
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public async Task ListFlushAsync(bool initialize, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ User gavin;
+ var addedItems = new List();
+ var finalIndexOrder = Enumerable.Range(0, 13).ToList();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ await (s.PersistAsync(gavin, cancellationToken));
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Add(item);
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ // Refresh added items
+ for (var i = 0; i < 5; i++)
+ {
+ addedItems[i] = await (s.GetAsync(addedItems[i].Id, cancellationToken));
+ }
+
+ // Add transient companies with Add
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Add(item);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Add transient companies with Insert
+ Sfi.Statistics.Clear();
+ using (var sqlLog = new SqlLogSpy())
+ {
+ for (var i = 10; i < 15; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Insert(i, item);
+ }
+
+ Assert.That(FindAllOccurrences(sqlLog.GetWholeLog(), "INSERT \n INTO"), Is.EqualTo(5));
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Add transient companies with Add
+ Sfi.Statistics.Clear();
+ for (var i = 15; i < 20; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Add(item);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(20));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Remove last 5 transient companies
+ Sfi.Statistics.Clear();
+ using (var sqlLog = new SqlLogSpy())
+ {
+ for (var i = 15; i < 20; i++)
+ {
+ Assert.That(gavin.Companies.Remove(addedItems[i]), Is.True);
+ }
+
+ Assert.That(FindAllOccurrences(sqlLog.GetWholeLog(), "INSERT \n INTO"), Is.EqualTo(10));
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Remove last 5 transient companies
+ Sfi.Statistics.Clear();
+ using (var sqlLog = new SqlLogSpy())
+ {
+ for (var i = 10; i < 15; i++)
+ {
+ gavin.Companies.RemoveAt(10);
+ }
+
+ Assert.That(FindAllOccurrences(sqlLog.GetWholeLog(), "DELETE \n FROM"), Is.EqualTo(5));
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(1));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(7));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Add transient companies with Add
+ Sfi.Statistics.Clear();
+ for (var i = 10; i < 15; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems[i] = item;
+ Assert.That(((IList)gavin.Companies).Add(item), Is.EqualTo(i));
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Remove last transient company
+ Sfi.Statistics.Clear();
+ using (var sqlLog = new SqlLogSpy())
+ {
+ Assert.That(gavin.Companies.Remove(addedItems[14]), Is.EqualTo(true));
+ var log = sqlLog.GetWholeLog();
+ Assert.That(FindAllOccurrences(log, "DELETE \n FROM"), Is.EqualTo(5));
+ Assert.That(FindAllOccurrences(log, "INSERT \n INTO"), Is.EqualTo(5));
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(14));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Test index getter
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Companies[0], Is.EqualTo(addedItems[0]));
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(14));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(1));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(3));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Remove last transient company
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Companies.Remove(addedItems[13]), Is.EqualTo(true));
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(13));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Test index setter
+ Sfi.Statistics.Clear();
+ gavin.Companies[0] = addedItems[0];
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(13));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(1));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(3));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Test manual flush after remove
+ Sfi.Statistics.Clear();
+ gavin.Companies.RemoveAt(12);
+ using (var sqlLog = new SqlLogSpy())
+ {
+ await (s.FlushAsync(cancellationToken));
+ Assert.That(FindAllOccurrences(sqlLog.GetWholeLog(), "DELETE \n FROM"), Is.EqualTo(1));
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(12));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Test manual flush after insert
+ Sfi.Statistics.Clear();
+ gavin.Companies.Add(new Company($"c{12}", 12, gavin));
+ using (var sqlLog = new SqlLogSpy())
+ {
+ await (s.FlushAsync(cancellationToken));
+ Assert.That(FindAllOccurrences(sqlLog.GetWholeLog(), "INSERT \n INTO"), Is.EqualTo(1));
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(13));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ for (var i = 0; i < gavin.Companies.Count; i++)
+ {
+ Assert.That(gavin.Companies[i].ListIndex, Is.EqualTo(i));
+ }
+
+ if (initialize)
+ {
+ using (var e = gavin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+ Assert.That(gavin.Companies.Count, Is.EqualTo(13));
+ Assert.That(gavin.Companies.Select(o => o.ListIndex), Is.EquivalentTo(finalIndexOrder));
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ Assert.That(gavin.Companies.Count, Is.EqualTo(13));
+ Assert.That(gavin.Companies.Select(o => o.ListIndex), Is.EquivalentTo(finalIndexOrder));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+
+ await (t.CommitAsync(cancellationToken));
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public async Task ListClearAsync(bool initialize, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ User gavin;
+ var addedItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ await (s.PersistAsync(gavin, cancellationToken));
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new CreditCard($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.CreditCards.Add(item);
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ s.FlushMode = FlushMode.Commit;
+
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ // Refresh added items
+ for (var i = 0; i < 5; i++)
+ {
+ addedItems[i] = await (s.GetAsync(addedItems[i].Id, cancellationToken));
+ }
+
+ var collection = gavin.CreditCards;
+
+ // Add transient permissions
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ var item = new CreditCard($"c{i}", i, gavin);
+ addedItems.Add(item);
+ collection.Insert(i, item);
+ }
+
+ Assert.That(collection.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ Sfi.Statistics.Clear();
+ collection.Clear();
+
+ Assert.That(collection.Count, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ // Readd two not loaded and two transient permissions
+ collection.Add(addedItems[0]);
+ collection.Add(addedItems[1]);
+ collection.Add(addedItems[5]);
+ collection.Add(addedItems[6]);
+
+ Assert.That(collection.Count, Is.EqualTo(4));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ // Remove one not loaded and one transient permissions
+ Assert.That(collection.Remove(addedItems[1]), Is.True);
+ Assert.That(collection.Remove(addedItems[6]), Is.True);
+
+ Assert.That(collection.Count, Is.EqualTo(2));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ // Remove not existing items
+ Assert.That(collection.Remove(addedItems[1]), Is.False);
+ Assert.That(collection.Remove(addedItems[6]), Is.False);
+
+ Assert.That(collection.Count, Is.EqualTo(2));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ if (initialize)
+ {
+ using (var e = collection.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.True);
+ Assert.That(collection.Count, Is.EqualTo(2));
+ }
+
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ var collection = gavin.CreditCards;
+ // As the cascade option is set to all, the clear operation will only work on
+ // transient permissions
+ Assert.That(collection.Count, Is.EqualTo(6));
+ for (var i = 0; i < 10; i++)
+ {
+ Assert.That(collection.Contains(addedItems[i]), i < 6 ? Is.True : (IResolveConstraint) Is.False);
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ await (t.CommitAsync(cancellationToken));
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public async Task ListIndexOperationsAsync(bool initialize, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ User gavin;
+ var finalIndexOrder = new List {6, 0, 4};
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ await (s.PersistAsync(gavin, cancellationToken));
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ gavin.Companies.Add(item);
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ // Current tracker state:
+ // Indexes: 0,1,2,3,4
+ // Queue: /
+ // RemoveDbIndexes: /
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ Sfi.Statistics.Clear();
+ gavin.Companies.Insert(1, new Company("c5", 5, gavin));
+ // Current tracker state:
+ // Indexes: 0,5,1,2,3,4
+ // Queue: {1, 5}
+ // RemoveDbIndexes: /
+
+ gavin.Companies.Insert(0, new Company("c6", 6, gavin));
+ // Current tracker state:
+ // Indexes: 6,0,5,1,2,3,4
+ // Queue: {0, 6}, {2, 5}
+ // RemoveDbIndexes: /
+
+ gavin.Companies.RemoveAt(4);
+ // Current tracker state:
+ // Indexes: 6,0,5,1,3,4
+ // Queue: {0, 6}, {2, 5}
+ // RemoveDbIndexes: 2
+
+ gavin.Companies.RemoveAt(3);
+ // Current tracker state:
+ // Indexes: 6,0,5,3,4
+ // Queue: {0, 6}, {2, 5}
+ // RemoveDbIndexes: 1,2
+
+ gavin.Companies.RemoveAt(3);
+ // Current tracker state:
+ // Indexes: 6,0,5,4
+ // Queue: {0, 6}, {2, 5}
+ // RemoveDbIndexes: 1,2,3
+
+ gavin.Companies.RemoveAt(2);
+ // Current tracker state:
+ // Indexes: 6,0,4
+ // Queue: {0, 6}
+ // RemoveDbIndexes: 1,2,3
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(3));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(3));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ gavin.UpdateCompaniesIndexes();
+
+ for (var i = 0; i < gavin.Companies.Count; i++)
+ {
+ Assert.That(gavin.Companies[i].OriginalIndex, Is.EqualTo(finalIndexOrder[i]));
+ }
+
+ if (initialize)
+ {
+ using (var e = gavin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+ Assert.That(gavin.Companies.Count, Is.EqualTo(3));
+ Assert.That(gavin.Companies.Select(o => o.OriginalIndex), Is.EquivalentTo(finalIndexOrder));
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ Assert.That(gavin.Companies.Count, Is.EqualTo(3));
+ Assert.That(gavin.Companies.Select(o => o.OriginalIndex), Is.EquivalentTo(finalIndexOrder));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+
+ await (t.CommitAsync(cancellationToken));
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public async Task SetAddAsync(bool initialize, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ User gavin;
+ Document hia;
+ Document hia2;
+ var addedDocuments = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ hia = new Document("HiA", "blah blah blah", gavin);
+ hia2 = new Document("HiA2", "blah blah blah blah", gavin);
+ gavin.Documents.Add(hia);
+ gavin.Documents.Add(hia2);
+ await (s.PersistAsync(gavin, cancellationToken));
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Documents.Count, Is.EqualTo(2));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Test adding documents with ISet interface
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ var document = new Document($"document{i}", $"content{i}", gavin);
+ addedDocuments.Add(document);
+ Assert.That(gavin.Documents.Add(document), Is.True);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(7));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Test adding documents with ICollection interface
+ Sfi.Statistics.Clear();
+ var documents = (ICollection) gavin.Documents;
+ for (var i = 0; i < 5; i++)
+ {
+ var document = new Document($"document2{i}", $"content{i}", gavin);
+ addedDocuments.Add(document);
+ documents.Add(document);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(12));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ // In this case we cannot determine whether the entities are transient or not so
+ // we are forced to check the database
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Test readding documents with ISet interface
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ Assert.That(gavin.Documents.Add(addedDocuments[i]), Is.False);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(12));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Test readding documents with ICollection interface
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ documents.Add(addedDocuments[i]);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(12));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Check existance of added documents
+ Sfi.Statistics.Clear();
+ foreach (var document in addedDocuments)
+ {
+ Assert.That(gavin.Documents.Contains(document), Is.True);
+ }
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Check existance of not loaded documents
+ Assert.That(gavin.Documents.Contains(hia), Is.True);
+ Assert.That(gavin.Documents.Contains(hia2), Is.True);
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Check existance of not existing documents
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Documents.Contains(new Document("test1", "content", gavin)), Is.False);
+ Assert.That(gavin.Documents.Contains(new Document("test2", "content", gavin)), Is.False);
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Test adding not loaded documents
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Documents.Add(hia), Is.False);
+ documents.Add(hia);
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(12));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ if (initialize)
+ {
+ using (var e = gavin.Documents.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.True);
+ Assert.That(gavin.Documents.Count, Is.EqualTo(12));
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ Assert.That(gavin.Documents.Count, Is.EqualTo(12));
+ Assert.That(gavin.Documents.Contains(hia2), Is.True);
+ Assert.That(gavin.Documents.Contains(hia), Is.True);
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ await (t.CommitAsync(cancellationToken));
+ }
+ }
+
+ [TestCase(false, false)]
+ [TestCase(false, true)]
+ [TestCase(true, false)]
+ [TestCase(true, true)]
+ public async Task SetAddDuplicatedAsync(bool initialize, bool flush, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ User gavin;
+ var addedItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ await (s.PersistAsync(gavin, cancellationToken));
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new Document($"d{i}", $"c{i}", gavin);
+ addedItems.Add(item);
+ gavin.Documents.Add(item);
+ gavin.Documents.Add(item);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(5));
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ // Refresh added items
+ for (var i = 0; i < 5; i++)
+ {
+ addedItems[i] = await (s.GetAsync(addedItems[i].Title, cancellationToken));
+ }
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Documents.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Readd items
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ Assert.That(gavin.Documents.Add(addedItems[i]), Is.False);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ if (flush)
+ {
+ await (s.FlushAsync(cancellationToken));
+ Assert.That(gavin.Documents.Count, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+ }
+
+ if (initialize)
+ {
+ using (var e = gavin.Documents.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.True);
+ Assert.That(gavin.Documents.Count, Is.EqualTo(5));
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ Assert.That(gavin.Documents.Count, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ await (t.CommitAsync(cancellationToken));
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public async Task SetAddTransientAsync(bool initialize, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ User gavin;
+ var addedItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ await (s.PersistAsync(gavin, cancellationToken));
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new UserPermission($"p{i}", gavin);
+ addedItems.Add(item);
+ gavin.Permissions.Add(item);
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ s.FlushMode = FlushMode.Commit;
+
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Permissions.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Permissions), Is.False);
+
+ // Test adding permissions with ICollection interface
+ Sfi.Statistics.Clear();
+ var items = (ICollection) gavin.Permissions;
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new UserPermission($"p2{i}", gavin);
+ addedItems.Add(item);
+ items.Add(item);
+ }
+
+ Assert.That(gavin.Permissions.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Permissions), Is.False);
+
+ // Test readding permissions with ICollection interface
+ Sfi.Statistics.Clear();
+ foreach (var item in addedItems.Skip(5))
+ {
+ items.Add(item);
+ }
+
+ Assert.That(gavin.Permissions.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Permissions), Is.False);
+
+ // Test adding not loaded permissions with ICollection interface
+ Sfi.Statistics.Clear();
+ foreach (var item in addedItems.Take(5))
+ {
+ items.Add(item);
+ }
+
+ Assert.That(gavin.Permissions.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Permissions), Is.False);
+
+ // Test adding loaded permissions with ICollection interface
+ Sfi.Statistics.Clear();
+ foreach (var item in s.Query())
+ {
+ items.Add(item);
+ }
+
+ Assert.That(gavin.Permissions.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(6));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Permissions), Is.False);
+
+
+ // Test adding permissions with ISet interface
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new UserPermission($"p3{i}", gavin);
+ addedItems.Add(item);
+ gavin.Permissions.Add(item);
+ }
+
+ Assert.That(gavin.Permissions.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Permissions), Is.False);
+
+ // Test readding permissions with ISet interface
+ Sfi.Statistics.Clear();
+ foreach (var item in addedItems.Skip(10))
+ {
+ gavin.Permissions.Add(item);
+ }
+
+ Assert.That(gavin.Permissions.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Permissions), Is.False);
+
+ // Test adding not loaded permissions with ISet interface
+ Sfi.Statistics.Clear();
+ foreach (var item in addedItems.Take(5))
+ {
+ gavin.Permissions.Add(item);
+ }
+
+ Assert.That(gavin.Permissions.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Permissions), Is.False);
+
+ // Test adding loaded permissions with ISet interface
+ Sfi.Statistics.Clear();
+ foreach (var item in s.Query())
+ {
+ gavin.Permissions.Add(item);
+ }
+
+ Assert.That(gavin.Permissions.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(6));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Permissions), Is.False);
+
+ if (initialize)
+ {
+ using (var e = gavin.Permissions.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Permissions), Is.True);
+ Assert.That(gavin.Permissions.Count, Is.EqualTo(15));
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ Assert.That(gavin.Permissions.Count, Is.EqualTo(15));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Permissions), Is.False);
+
+ await (t.CommitAsync(cancellationToken));
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public async Task SetRemoveAsync(bool initialize, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ User gavin;
+ var addedDocuments = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ for (var i = 0; i < 5; i++)
+ {
+ var document = new Document($"document{i}", $"content{i}", gavin);
+ addedDocuments.Add(document);
+ gavin.Documents.Add(document);
+ }
+
+ await (s.PersistAsync(gavin, cancellationToken));
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ // Refresh added items
+ for (var i = 0; i < 5; i++)
+ {
+ addedDocuments[i] = await (s.GetAsync(addedDocuments[i].Title, cancellationToken));
+ }
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Documents.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Add new documents
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ var document = new Document($"document2{i}", $"content{i}", gavin);
+ addedDocuments.Add(document);
+ ((ICollection)gavin.Documents).Add(document);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Test removing existing documents
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ Assert.That(gavin.Documents.Remove(addedDocuments[i]), Is.True);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Test removing removed existing documents
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ Assert.That(gavin.Documents.Contains(addedDocuments[i]), Is.False);
+ Assert.That(gavin.Documents.Remove(addedDocuments[i]), Is.False);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Test removing not existing documents
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ var document = new Document($"test{i}", "content", gavin);
+ Assert.That(gavin.Documents.Remove(document), Is.False);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Test removing newly added documents
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ Assert.That(gavin.Documents.Contains(addedDocuments[i]), Is.True);
+ Assert.That(gavin.Documents.Remove(addedDocuments[i]), Is.True);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Test removing removed newly added documents
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ Assert.That(gavin.Documents.Contains(addedDocuments[i]), Is.False);
+ Assert.That(gavin.Documents.Remove(addedDocuments[i]), Is.False);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Test removing not existing documents
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ var document = new Document($"test{i}", "content", gavin);
+ Assert.That(gavin.Documents.Remove(document), Is.False);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ if (initialize)
+ {
+ using (var e = gavin.Documents.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.True);
+ Assert.That(gavin.Documents.Count, Is.EqualTo(0));
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ Assert.That(gavin.Documents.Count, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ await (t.CommitAsync(cancellationToken));
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public async Task SetClearAsync(bool initialize, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ User gavin;
+ var addedItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ await (s.PersistAsync(gavin, cancellationToken));
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new UserPermission($"p{i}", gavin);
+ addedItems.Add(item);
+ gavin.Permissions.Add(item);
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ s.FlushMode = FlushMode.Commit;
+
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ // Refresh added items
+ for (var i = 0; i < 5; i++)
+ {
+ addedItems[i] = await (s.GetAsync(addedItems[i].Id, cancellationToken));
+ }
+
+ var collection = gavin.Permissions;
+
+ Sfi.Statistics.Clear();
+ Assert.That(collection.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ // Add transient permissions
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new UserPermission($"p2{i}", gavin);
+ addedItems.Add(item);
+ collection.Add(item);
+ }
+
+ Assert.That(collection.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ Sfi.Statistics.Clear();
+ collection.Clear();
+
+ Assert.That(collection.Count, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ // Readd two not loaded and two transient permissions
+ Assert.That(collection.Add(addedItems[0]), Is.True);
+ Assert.That(collection.Add(addedItems[1]), Is.True);
+ Assert.That(collection.Add(addedItems[5]), Is.True);
+ Assert.That(collection.Add(addedItems[6]), Is.True);
+
+ Assert.That(collection.Count, Is.EqualTo(4));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ // Remove one not loaded and one transient permissions
+ Assert.That(collection.Remove(addedItems[1]), Is.True);
+ Assert.That(collection.Remove(addedItems[6]), Is.True);
+
+ Assert.That(collection.Count, Is.EqualTo(2));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ // Remove not existing items
+ Assert.That(collection.Remove(addedItems[1]), Is.False);
+ Assert.That(collection.Remove(addedItems[6]), Is.False);
+
+ Assert.That(collection.Count, Is.EqualTo(2));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ if (initialize)
+ {
+ using (var e = collection.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.True);
+ Assert.That(collection.Count, Is.EqualTo(2));
+ }
+
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ var collection = gavin.Permissions;
+ // As the cascade option is set to all, the clear operation will only work on
+ // transient permissions
+ Assert.That(collection.Count, Is.EqualTo(6));
+ for (var i = 0; i < 10; i++)
+ {
+ Assert.That(collection.Contains(addedItems[i]), i < 6 ? Is.True : (IResolveConstraint) Is.False);
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ await (t.CommitAsync(cancellationToken));
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public async Task MapAddAsync(bool initialize, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ User gavin;
+ UserSetting setting;
+ var addedSettings = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ await (s.PersistAsync(gavin, cancellationToken));
+
+ for (var i = 0; i < 5; i++)
+ {
+ setting = new UserSetting($"s{i}", $"data{i}", gavin);
+ addedSettings.Add(setting);
+ gavin.Settings.Add(setting.Name, setting);
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Settings.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Test adding settings with Add method
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ setting = new UserSetting($"s2{i}", $"data{i}", gavin);
+ addedSettings.Add(setting);
+ gavin.Settings.Add(setting.Name, setting);
+ }
+
+ Assert.That(gavin.Settings.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Test adding settings with []
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ setting = new UserSetting($"s3{i}", $"data{i}", gavin);
+ addedSettings.Add(setting);
+
+ gavin.Settings[setting.Name] = setting;
+ }
+
+ Assert.That(gavin.Settings.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Check existance of added settings
+ Sfi.Statistics.Clear();
+ foreach (var item in addedSettings.Skip(5))
+ {
+ Assert.That(gavin.Settings.ContainsKey(item.Name), Is.True);
+ Assert.That(gavin.Settings.Contains(new KeyValuePair(item.Name, item)), Is.True);
+ }
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Check existance of not loaded settings
+ foreach (var item in addedSettings.Take(5))
+ {
+ Assert.That(gavin.Settings.ContainsKey(item.Name), Is.True);
+ }
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Check existance of not existing settings
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Settings.ContainsKey("test"), Is.False);
+ Assert.That(gavin.Settings.ContainsKey("test2"), Is.False);
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Try to add an existing setting
+ Assert.Throws(() => gavin.Settings.Add("s0", new UserSetting("s0", "data", gavin)));
+ Assert.Throws(() => gavin.Settings.Add("s20", new UserSetting("s20", "data", gavin)));
+ Assert.Throws(() => gavin.Settings.Add("s30", new UserSetting("s30", "data", gavin)));
+
+ // Get values of not loaded keys
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Settings.TryGetValue("s0", out setting), Is.True);
+ Assert.That(setting.Id, Is.EqualTo(addedSettings[0].Id));
+ Assert.That(gavin.Settings["s0"].Id, Is.EqualTo(addedSettings[0].Id));
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Get values of newly added keys
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Settings.TryGetValue("s20", out setting), Is.True);
+ Assert.That(setting, Is.EqualTo(addedSettings[5]));
+ Assert.That(gavin.Settings["s20"], Is.EqualTo(addedSettings[5]));
+ Assert.That(gavin.Settings.TryGetValue("s30", out setting), Is.True);
+ Assert.That(setting, Is.EqualTo(addedSettings[10]));
+ Assert.That(gavin.Settings["s30"], Is.EqualTo(addedSettings[10]));
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Try to get a non existing setting
+ Assert.That(gavin.Settings.TryGetValue("test", out setting), Is.False);
+ Assert.That(gavin.Settings.TryGetValue("test2", out setting), Is.False);
+ Assert.Throws(() =>
+ {
+ setting = gavin.Settings["test"];
+ });
+ Assert.Throws(() =>
+ {
+ setting = gavin.Settings["test2"];
+ });
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(4));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ if (initialize)
+ {
+ using (var e = gavin.Settings.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.True);
+ Assert.That(gavin.Settings.Count, Is.EqualTo(15));
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ Assert.That(gavin.Settings.Count, Is.EqualTo(15));
+ Assert.That(gavin.Settings.ContainsKey(addedSettings[0].Name), Is.True);
+ Assert.That(gavin.Settings.ContainsKey(addedSettings[5].Name), Is.True);
+ Assert.That(gavin.Settings.ContainsKey(addedSettings[10].Name), Is.True);
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ await (t.CommitAsync(cancellationToken));
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public async Task MapSetAsync(bool initialize, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ User gavin;
+ UserSetting setting;
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ await (s.PersistAsync(gavin, cancellationToken));
+
+ for (var i = 0; i < 5; i++)
+ {
+ setting = new UserSetting($"s{i}", $"data{i}", gavin);
+ gavin.Settings.Add(setting.Name, setting);
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Settings.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Set a key that does not exist in db and it is not in the queue
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ setting = new UserSetting($"s2{i}", $"data{i}", gavin);
+ gavin.Settings[setting.Name] = setting;
+ }
+
+ Assert.That(gavin.Settings.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Set a key that does not exist in db and it is in the queue
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ setting = new UserSetting($"s2{i}", $"data{i}", gavin);
+ gavin.Settings[setting.Name] = setting;
+ }
+
+ Assert.That(gavin.Settings.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Set a key that exists in db and it is not in the queue
+ Sfi.Statistics.Clear();
+ gavin.Settings["s0"] = new UserSetting("s0", "s0", gavin);
+
+ Assert.That(gavin.Settings.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Set a key that exists in db and it is in the queue
+ Sfi.Statistics.Clear();
+ gavin.Settings["s0"] = new UserSetting("s0", "s0", gavin);
+
+ Assert.That(gavin.Settings.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Set a key that exists in db and it is in the removal queue
+ Assert.That(gavin.Settings.Remove("s1"), Is.True);
+ Sfi.Statistics.Clear();
+ gavin.Settings["s1"] = new UserSetting("s1", "s1", gavin);
+
+ Assert.That(gavin.Settings.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ if (initialize)
+ {
+ using (var e = gavin.Settings.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.True);
+ Assert.That(gavin.Settings.Count, Is.EqualTo(10));
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ Assert.That(gavin.Settings.Count, Is.EqualTo(10));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ await (t.CommitAsync(cancellationToken));
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public async Task MapRemoveAsync(bool initialize, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ User gavin;
+ UserSetting setting;
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ await (s.PersistAsync(gavin, cancellationToken));
+
+ for (var i = 0; i < 5; i++)
+ {
+ setting = new UserSetting($"s{i}", $"data{i}", gavin);
+ gavin.Settings.Add(setting.Name, setting);
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Settings.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ setting = new UserSetting($"s2{i}", $"data{i}", gavin);
+ gavin.Settings[setting.Name] = setting;
+ }
+
+ Assert.That(gavin.Settings.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Remove a key that exists in db and it is not in the queue and removal queue
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Settings.Remove("s0"), Is.True);
+
+ Assert.That(gavin.Settings.Count, Is.EqualTo(9));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Remove a key that exists in db and it is in the queue
+ var item = gavin.Settings["s1"];
+ Assert.That(gavin.Settings.Remove("s1"), Is.True);
+ gavin.Settings.Add(item.Name, item);
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Settings.Remove("s1"), Is.True);
+
+ Assert.That(gavin.Settings.Count, Is.EqualTo(8));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Remove a key that does not exist in db and it is not in the queue
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Settings.Remove("test"), Is.False);
+
+ Assert.That(gavin.Settings.Count, Is.EqualTo(8));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Remove a key that does not exist in db and it is in the queue
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Settings.Remove("s20"), Is.True);
+
+ Assert.That(gavin.Settings.Count, Is.EqualTo(7));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Remove a key that exists in db and it is in the removal queue
+ Assert.That(gavin.Settings.Remove("s2"), Is.True);
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Settings.Remove("s2"), Is.False);
+
+ Assert.That(gavin.Settings.Count, Is.EqualTo(6));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ if (initialize)
+ {
+ using (var e = gavin.Settings.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.True);
+ Assert.That(gavin.Settings.Count, Is.EqualTo(6));
+ }
+
+ await (t.CommitAsync(cancellationToken));
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = await (s.GetAsync("gavin", cancellationToken));
+ Assert.That(gavin.Settings.Count, Is.EqualTo(6));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ await (t.CommitAsync(cancellationToken));
}
}
@@ -395,5 +3263,22 @@ public async Task AddToUninitializedSetWithLaterLazyLoadAsync()
await (t.CommitAsync());
}
}
+
+ private int FindAllOccurrences(string source, string substring)
+ {
+ if (source == null)
+ {
+ return 0;
+ }
+ int n = 0, count = 0;
+ while ((n = source.IndexOf(substring, n, StringComparison.InvariantCulture)) != -1)
+ {
+ n += substring.Length;
+ ++count;
+ }
+ return count;
+ }
+
+ private bool IsNativeIdentityGenerator => Dialect.NativeIdentifierGeneratorClass == typeof(IdentityGenerator);
}
}
diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH2922/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH2922/Fixture.cs
new file mode 100644
index 00000000000..1f84df22b83
--- /dev/null
+++ b/src/NHibernate.Test/Async/NHSpecificTest/NH2922/Fixture.cs
@@ -0,0 +1,105 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by AsyncGenerator.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+
+using System.Linq;
+using NUnit.Framework;
+
+namespace NHibernate.Test.NHSpecificTest.NH2922
+{
+ using System.Threading.Tasks;
+ [TestFixture]
+ public class FixtureAsync : BugTestCase
+ {
+ protected override void OnSetUp()
+ {
+ using (var session = OpenSession())
+ {
+ var a = new Store {Id = 1, Name = "A"};
+ var b = new Store {Id = 2, Name = "B"};
+ var jack = new Employee {Id = 3, Name = "Jack", Store = a};
+ a.Staff.Add(jack);
+
+ session.Save(a);
+ session.Save(b);
+ session.Save(jack);
+ session.Flush();
+ }
+ }
+
+ protected override void OnTearDown()
+ {
+ using (var session = OpenSession())
+ {
+ session.Delete("from System.Object");
+ session.Flush();
+ }
+ }
+
+ [Test]
+ public async Task ReparentedCase1Async()
+ {
+ using (var session = OpenSession())
+ {
+ var a = await (session.GetAsync(1)); // Order of loading affects outcome
+ var b = await (session.GetAsync(2));
+
+ // Move employee to different store
+ var jack = a.Staff.Single(x => x.Name == "Jack");
+
+ a.Staff.Remove(jack);
+ jack.Store = b;
+ b.Staff.Add(jack);
+
+ await (session.FlushAsync());
+ session.Clear();
+ }
+
+ using (var session = OpenSession())
+ {
+ var a = await (session.GetAsync(1));
+ var b = await (session.GetAsync(2));
+
+ Assert.That(a.Staff.Count, Is.EqualTo(0));
+ Assert.That(b.Staff.Count, Is.EqualTo(1));
+ }
+ }
+
+ [Test]
+ public async Task ReparentedCase2Async()
+ {
+ using (var session = OpenSession())
+ {
+ var b = await (session.GetAsync(2));
+ var a = await (session.GetAsync(1)); // Order of loading affects outcome
+
+ // Move employee to different store
+ var jack = a.Staff.Single(x => x.Name == "Jack");
+
+ a.Staff.Remove(jack);
+ jack.Store = b;
+ b.Staff.Add(jack);
+
+ await (session.FlushAsync());
+ session.Clear();
+ }
+
+ using (var session = OpenSession())
+ {
+ var jack = await (session.GetAsync(3));
+ var b = await (session.GetAsync(2));
+ var a = await (session.GetAsync(1));
+
+ Assert.That(jack, Is.Not.Null);
+ Assert.That(a.Staff.Count, Is.EqualTo(0));
+ Assert.That(b.Staff.Count, Is.EqualTo(1));
+ }
+ }
+ }
+}
diff --git a/src/NHibernate.Test/CollectionCompositeKey/Child.cs b/src/NHibernate.Test/CollectionCompositeKey/Child.cs
new file mode 100644
index 00000000000..f6e54ba4eb5
--- /dev/null
+++ b/src/NHibernate.Test/CollectionCompositeKey/Child.cs
@@ -0,0 +1,43 @@
+
+namespace NHibernate.Test.CollectionCompositeKey
+{
+ public class Child
+ {
+ protected Child()
+ {
+ }
+
+ public Child(int number, string name, Parent parent)
+ {
+ Id = new ChildCompositeId()
+ {
+ Number = number,
+ ParentNumber = parent.Number,
+ ParentCode = parent.Code
+ };
+ Name = name;
+ }
+
+ public virtual ChildCompositeId Id { get; set; }
+
+ public virtual string Name { get; set; }
+
+ public virtual Parent Parent { get; set; }
+
+ public virtual Parent ParentByName { get; set; }
+
+ public virtual string ParentName { get; set; }
+
+ public virtual Parent ParentByReference { get; set; }
+
+ public virtual string ParentReferenceCode { get; set; }
+
+ public virtual int ParentReferenceNumber { get; set; }
+
+ public virtual string ParentCode { get; set; }
+
+ public virtual int ParentNumber { get; set; }
+
+ public virtual ChildComponent Component { get; set; } = new ChildComponent();
+ }
+}
diff --git a/src/NHibernate.Test/CollectionCompositeKey/ChildComponent.cs b/src/NHibernate.Test/CollectionCompositeKey/ChildComponent.cs
new file mode 100644
index 00000000000..7c6573ef2b0
--- /dev/null
+++ b/src/NHibernate.Test/CollectionCompositeKey/ChildComponent.cs
@@ -0,0 +1,12 @@
+
+namespace NHibernate.Test.CollectionCompositeKey
+{
+ public class ChildComponent
+ {
+ public virtual Parent Parent { get; set; }
+
+ public virtual string ParentCode { get; set; }
+
+ public virtual int ParentNumber { get; set; }
+ }
+}
diff --git a/src/NHibernate.Test/CollectionCompositeKey/ChildCompositeId.cs b/src/NHibernate.Test/CollectionCompositeKey/ChildCompositeId.cs
new file mode 100644
index 00000000000..2d28814096c
--- /dev/null
+++ b/src/NHibernate.Test/CollectionCompositeKey/ChildCompositeId.cs
@@ -0,0 +1,27 @@
+
+namespace NHibernate.Test.CollectionCompositeKey
+{
+ public class ChildCompositeId
+ {
+ public virtual int Number { get; set; }
+
+ public virtual string ParentCode { get; set; }
+
+ public virtual int ParentNumber { get; set; }
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is ChildCompositeId key))
+ {
+ return false;
+ }
+
+ return Number.Equals(key.Number) && ParentCode.Equals(key.ParentCode) && ParentNumber.Equals(key.ParentNumber);
+ }
+
+ public override int GetHashCode()
+ {
+ return Number.GetHashCode() ^ ParentCode.GetHashCode() ^ ParentNumber.GetHashCode();
+ }
+ }
+}
diff --git a/src/NHibernate.Test/CollectionCompositeKey/CollectionOwner.hbm.xml b/src/NHibernate.Test/CollectionCompositeKey/CollectionOwner.hbm.xml
new file mode 100644
index 00000000000..e9dba311498
--- /dev/null
+++ b/src/NHibernate.Test/CollectionCompositeKey/CollectionOwner.hbm.xml
@@ -0,0 +1,157 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/NHibernate.Test/CollectionCompositeKey/Fixture.cs b/src/NHibernate.Test/CollectionCompositeKey/Fixture.cs
new file mode 100644
index 00000000000..c82c4a0bc2d
--- /dev/null
+++ b/src/NHibernate.Test/CollectionCompositeKey/Fixture.cs
@@ -0,0 +1,205 @@
+using System;
+using System.Collections.Generic;
+using NHibernate.Event;
+using NHibernate.Persister.Collection;
+using NUnit.Framework;
+using NUnit.Framework.Constraints;
+
+namespace NHibernate.Test.CollectionCompositeKey
+{
+ [TestFixture]
+ public class Fixture : TestCase
+ {
+ private readonly Parent _parentId = new Parent("1", 1);
+ private int _currentChildId = 1;
+ private int _currentGrandChildId = 1;
+
+ protected override string[] Mappings => new [] { "CollectionCompositeKey.CollectionOwner.hbm.xml" };
+
+ protected override string MappingsAssembly => "NHibernate.Test";
+
+ protected override string CacheConcurrencyStrategy => null;
+
+ protected override void OnSetUp()
+ {
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ var parent = CreateParent(_parentId.Code, _parentId.Number);
+
+ s.Save(parent);
+ t.Commit();
+ }
+ }
+
+ protected override void OnTearDown()
+ {
+ using (var session = OpenSession())
+ using (var tx = session.BeginTransaction())
+ {
+ session.Delete("from GrandChild");
+ session.Delete("from Child");
+ session.Delete("from Parent");
+ tx.Commit();
+ }
+ base.OnTearDown();
+ }
+
+ [TestCase(nameof(Parent.Children), true, true)]
+ [TestCase(nameof(Parent.ChildrenByForeignKeys), true, false)]
+ [TestCase(nameof(Parent.ChildrenByComponent), true, true)]
+ [TestCase(nameof(Parent.ChildrenByComponentForeignKeys), true, false)]
+ [TestCase(nameof(Parent.ChildrenNoProperties), false, false)]
+ [TestCase(nameof(Parent.ChildrenByUniqueKey), true, true)]
+ [TestCase(nameof(Parent.ChildrenByUniqueKeyNoManyToOne), true, false)]
+ [TestCase(nameof(Parent.ChildrenByCompositeUniqueKey), true, true)]
+ [TestCase(nameof(Parent.ChildrenByCompositeUniqueKeyNoManyToOne), true, false)]
+ public void TestGetElementOwnerForChildCollections(string collectionProperty, bool propertyExists, bool hasManyToOne)
+ {
+ TestGetElementOwnerForChildCollections(collectionProperty, propertyExists, hasManyToOne, (parent, child) => child.Id);
+ }
+
+ [TestCase(nameof(Parent.GrandChildren), true, true)]
+ public void TestGetElementOwnerForGrandChildCollections(string collectionProperty, bool propertyExists, bool hasManyToOne)
+ {
+ TestGetElementOwnerForChildCollections(collectionProperty, propertyExists, hasManyToOne, GetGrandChildId);
+ }
+
+ private static object GetGrandChildId(Parent parent, GrandChild child)
+ {
+ if (parent == null)
+ {
+ return null; // Not supported
+ }
+
+ child.GrandParent = parent;
+ return child;
+ }
+
+ private void TestGetElementOwnerForChildCollections(string collectionProperty, bool propertyExists, bool hasManyToOne, Func getChildId)
+ where TChild : class
+ {
+ var persister = Sfi.GetEntityPersister(typeof(Parent).FullName);
+ var collPersister = GetCollectionPersister(collectionProperty);
+ TChild firstChild = null;
+
+ var propertyIndex = -1;
+ for (var i = 0; i < persister.PropertyNames.Length; i++)
+ {
+ if (persister.PropertyNames[i] == collectionProperty)
+ {
+ propertyIndex = i;
+ break;
+ }
+ }
+
+ Assert.That(propertyIndex, Is.Not.EqualTo(-1));
+
+ // Test when collection is loaded
+ using (var s = (IEventSource) OpenSession())
+ using (var tx = s.BeginTransaction())
+ {
+ var parent = s.Get(_parentId);
+ Assert.That(parent, Is.Not.Null);
+
+ var collection = (IList) persister.GetPropertyValue(parent, propertyIndex);
+ foreach (var child in collection)
+ {
+ if (firstChild == null)
+ {
+ firstChild = child;
+ }
+
+ Assert.That(collPersister.GetElementOwner(child, s), propertyExists ? Is.EqualTo(parent) : (IResolveConstraint) Is.Null);
+ }
+
+ tx.Commit();
+ }
+
+ Assert.That(firstChild, Is.Not.Null);
+
+ // Test when collection is not loaded
+ using (var s = (IEventSource) OpenSession())
+ using (var tx = s.BeginTransaction())
+ {
+ var parent = s.Get(_parentId);
+ var child = s.Get(getChildId(parent, firstChild));
+ Assert.That(parent, Is.Not.Null);
+ Assert.That(child, Is.Not.Null);
+
+ Assert.That(collPersister.GetElementOwner(child, s), propertyExists ? Is.EqualTo(parent) : (IResolveConstraint) Is.Null);
+
+ tx.Commit();
+ }
+
+ // Test when only the child is loaded
+ using (var s = (IEventSource) OpenSession())
+ using (var tx = s.BeginTransaction())
+ {
+ var id = getChildId(null, firstChild);
+ if (id != null)
+ {
+ var child = s.Get(id);
+ Assert.That(child, Is.Not.Null);
+
+ Assert.That(collPersister.GetElementOwner(child, s), hasManyToOne ? Is.InstanceOf() : (IResolveConstraint) Is.Null);
+ }
+
+ tx.Commit();
+ }
+
+ // Test transient
+ using (var s = (IEventSource) OpenSession())
+ using (var tx = s.BeginTransaction())
+ {
+ var parent = CreateParent("2", 2);
+ var collection = (IList) persister.GetPropertyValue(parent, propertyIndex);
+
+ foreach (var child in collection)
+ {
+ Assert.That(collPersister.GetElementOwner(child, s), hasManyToOne ? Is.EqualTo(parent) : (IResolveConstraint) Is.Null);
+ }
+
+ tx.Commit();
+ }
+ }
+
+ private AbstractCollectionPersister GetCollectionPersister(string collectionProperty)
+ {
+ return (AbstractCollectionPersister) Sfi.GetCollectionPersister($"{typeof(Parent).FullName}.{collectionProperty}");
+ }
+
+ private Parent CreateParent(string code, int number)
+ {
+ var parent = new Parent(code, number)
+ {
+ Name = $"parent{number}",
+ ReferenceCode = code,
+ ReferenceNumber = number
+ };
+
+ parent.Children.Add(new Child(_currentChildId++, "child", parent) { Parent = parent });
+ parent.ChildrenByForeignKeys.Add(new Child(_currentChildId++, "childFk", parent) { ParentNumber = parent.Number, ParentCode = parent.Code });
+ parent.ChildrenByComponent.Add(new Child(_currentChildId++, "childCo", parent) { Component = new ChildComponent { Parent = parent } });
+ parent.ChildrenByComponentForeignKeys.Add(
+ new Child(_currentChildId++, "childCoFk", parent)
+ {
+ Component = new ChildComponent { ParentNumber = parent.Number, ParentCode = parent.Code }
+ });
+ parent.ChildrenNoProperties.Add(new Child(_currentChildId++, "childNp", parent));
+ parent.ChildrenByUniqueKey.Add(new Child(_currentChildId++, "childUk", parent) { ParentByName = parent });
+ parent.ChildrenByUniqueKeyNoManyToOne.Add(new Child(_currentChildId++, "childUkFk", parent) { ParentName = parent.Name });
+ parent.ChildrenByCompositeUniqueKey.Add(new Child(_currentChildId++, "childCoUk", parent) { ParentByReference = parent });
+ parent.ChildrenByCompositeUniqueKeyNoManyToOne.Add(
+ new Child(_currentChildId++, "childCoUkFk", parent)
+ {
+ ParentReferenceCode = parent.ReferenceCode,
+ ParentReferenceNumber = parent.ReferenceNumber
+ });
+
+ parent.GrandChildren.Add(new GrandChild(_currentGrandChildId, "grandChild", parent));
+
+ return parent;
+ }
+ }
+}
diff --git a/src/NHibernate.Test/CollectionCompositeKey/GrandChild.cs b/src/NHibernate.Test/CollectionCompositeKey/GrandChild.cs
new file mode 100644
index 00000000000..2c362a18b79
--- /dev/null
+++ b/src/NHibernate.Test/CollectionCompositeKey/GrandChild.cs
@@ -0,0 +1,38 @@
+
+namespace NHibernate.Test.CollectionCompositeKey
+{
+ public class GrandChild
+ {
+ protected GrandChild()
+ {
+ }
+
+ public GrandChild(int number, string name, Parent grandParent)
+ {
+ Number = number;
+ GrandParent = grandParent;
+ Name = name;
+ }
+
+ public virtual int Number { get; set; }
+
+ public virtual Parent GrandParent { get; set; }
+
+ public virtual string Name { get; set; }
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is GrandChild key))
+ {
+ return false;
+ }
+
+ return Number.Equals(key.Number) && GrandParent.Equals(key.GrandParent);
+ }
+
+ public override int GetHashCode()
+ {
+ return Number.GetHashCode() ^ GrandParent.GetHashCode();
+ }
+ }
+}
diff --git a/src/NHibernate.Test/CollectionCompositeKey/Parent.cs b/src/NHibernate.Test/CollectionCompositeKey/Parent.cs
new file mode 100644
index 00000000000..b793bb5fe6d
--- /dev/null
+++ b/src/NHibernate.Test/CollectionCompositeKey/Parent.cs
@@ -0,0 +1,72 @@
+using System.Collections.Generic;
+
+namespace NHibernate.Test.CollectionCompositeKey
+{
+ public class Parent
+ {
+ protected Parent() { }
+
+ public Parent(string code, int number)
+ {
+ Code = code;
+ Number = number;
+ }
+
+ public virtual string Code { get; set; }
+
+ public virtual int Number { get; set; }
+
+ public virtual string Name { get; set; }
+
+ public virtual int ReferenceNumber { get; set; }
+
+ public virtual string ReferenceCode { get; set; }
+
+ public virtual IList ChildrenByCompositeId { get; set; } = new List();
+
+ public virtual IList Children { get; set; } = new List();
+
+ public virtual IList ChildrenByForeignKeys { get; set; } = new List();
+
+ public virtual IList ChildrenByComponent { get; set; } = new List();
+
+ public virtual IList ChildrenByComponentForeignKeys { get; set; } = new List();
+
+ public virtual IList ChildrenByUniqueKey { get; set; } = new List();
+
+ public virtual IList ChildrenByUniqueKeyNoManyToOne { get; set; } = new List();
+
+ public virtual IList ChildrenByCompositeUniqueKey { get; set; } = new List();
+
+ public virtual IList ChildrenByCompositeUniqueKeyNoManyToOne { get; set; } = new List();
+
+ public virtual IList ChildrenNoProperties { get; set; } = new List();
+
+ public virtual IList GrandChildren { get; set; } = new List();
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is Parent key))
+ {
+ return false;
+ }
+
+ if (string.IsNullOrEmpty(Code))
+ {
+ return ReferenceNumber.Equals(key.ReferenceNumber) && ReferenceCode.Equals(key.ReferenceCode);
+ }
+
+ return Number.Equals(key.Number) && Code.Equals(key.Code);
+ }
+
+ public override int GetHashCode()
+ {
+ if (string.IsNullOrEmpty(Code))
+ {
+ return ReferenceNumber.GetHashCode() ^ ReferenceCode.GetHashCode();
+ }
+
+ return Number.GetHashCode() ^ Code.GetHashCode();
+ }
+ }
+}
diff --git a/src/NHibernate.Test/Extralazy/Company.cs b/src/NHibernate.Test/Extralazy/Company.cs
new file mode 100644
index 00000000000..728a5f85e8d
--- /dev/null
+++ b/src/NHibernate.Test/Extralazy/Company.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace NHibernate.Test.Extralazy
+{
+ public class Company
+ {
+ protected Company() { }
+
+ public Company(string name, int index, User owner)
+ {
+ Name = name;
+ Owner = owner;
+ OriginalIndex = ListIndex = index;
+ }
+
+ public virtual int Id { get; set; }
+
+ public virtual int ListIndex { get; set; }
+
+ public virtual int OriginalIndex { get; set; }
+
+ public virtual string Name { get; set; }
+
+ public virtual User Owner { get; set; }
+ }
+}
diff --git a/src/NHibernate.Test/Extralazy/CreditCard.cs b/src/NHibernate.Test/Extralazy/CreditCard.cs
new file mode 100644
index 00000000000..ffeb98a831b
--- /dev/null
+++ b/src/NHibernate.Test/Extralazy/CreditCard.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace NHibernate.Test.Extralazy
+{
+ public class CreditCard
+ {
+ protected CreditCard() { }
+
+ public CreditCard(string name, int index, User owner)
+ {
+ Name = name;
+ Owner = owner;
+ OriginalIndex = ListIndex = index;
+ }
+
+ public virtual int Id { get; set; }
+
+ public virtual int ListIndex { get; set; }
+
+ public virtual int OriginalIndex { get; set; }
+
+ public virtual string Name { get; set; }
+
+ public virtual User Owner { get; set; }
+ }
+}
diff --git a/src/NHibernate.Test/Extralazy/ExtraLazyFixture.cs b/src/NHibernate.Test/Extralazy/ExtraLazyFixture.cs
index 248abdf63e8..4aa25902b46 100644
--- a/src/NHibernate.Test/Extralazy/ExtraLazyFixture.cs
+++ b/src/NHibernate.Test/Extralazy/ExtraLazyFixture.cs
@@ -1,7 +1,11 @@
+using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
+using NHibernate.Cfg;
+using NHibernate.Id;
using NUnit.Framework;
+using NUnit.Framework.Constraints;
namespace NHibernate.Test.Extralazy
{
@@ -23,12 +27,2875 @@ protected override string CacheConcurrencyStrategy
get { return null; }
}
+ protected override void Configure(Configuration configuration)
+ {
+ configuration.SetProperty(Cfg.Environment.GenerateStatistics, "true");
+ }
+
protected override void OnTearDown()
{
using (var s = OpenSession())
using (var t = s.BeginTransaction())
{
- s.Delete("from System.Object");
+ s.Delete("from System.Object");
+ t.Commit();
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public void MapAddChildSaveChangeParent(bool initialize)
+ {
+ User gavin;
+ User turin;
+ var gavinItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ turin = new User("turin", "tiger");
+ s.Persist(gavin);
+ s.Persist(turin);
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new UserSetting($"g{i}", $"data{i}", gavin);
+ gavinItems.Add(item);
+ gavin.Settings.Add(item.Name, item);
+
+ item = new UserSetting($"t{i}", $"data{i}", turin);
+ turin.Settings.Add(item.Name, item);
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ turin = s.Get("turin");
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Settings.Count, Is.EqualTo(5));
+ Assert.That(turin.Settings.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+ Assert.That(NHibernateUtil.IsInitialized(turin.Settings), Is.False);
+
+ // Save companies and then add them to the collection
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ var item = new UserSetting($"c{i}", $"data{i}", gavin);
+ s.Save(item);
+ gavinItems.Add(item);
+ }
+
+ for (var i = 5; i < 10; i++)
+ {
+ gavin.Settings.Add(gavinItems[i].Name, gavinItems[i]);
+ }
+
+ Assert.That(gavin.Settings.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Add companies to the collection and then save them
+ Sfi.Statistics.Clear();
+ for (var i = 10; i < 15; i++)
+ {
+ var item = new UserSetting($"c{i}", $"data{i}", gavin);
+ gavin.Settings.Add(item.Name, item);
+ gavinItems.Add(item);
+ s.Save(item);
+ }
+
+ Assert.That(gavin.Settings.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Remove added items from the collection and add them to a different parent
+ foreach (var item in gavinItems.Skip(5).Take(5))
+ {
+ gavin.Settings.Remove(item.Name);
+
+ item.Owner = turin;
+ turin.Settings.Add(item.Name, item);
+ }
+
+ // Remove added items from the collection
+ for (var i = 10; i < 15; i++)
+ {
+ var item = gavinItems[i];
+ gavin.Settings.Remove(item.Name);
+ // When identity is used for the primary key the item will be already inserted in the database,
+ // so the RemoveAt method will mark it as an orphan which will be deleted on flush.
+ // The same would work for an initialized collection as the collection snapshot would contain the item.
+ // When dealing with an id generator that supports a delayed insert, we have to trigger a delete
+ // for the item as it is currently scheduled for insertion.
+ if (IsNativeIdentityGenerator)
+ {
+ if (i % 2 != 0)
+ {
+ item.Owner = null;
+ }
+ }
+ else
+ {
+ s.Delete(item);
+ }
+ }
+
+ Assert.That(gavin.Settings.Count, Is.EqualTo(5));
+ Assert.That(turin.Settings.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+ Assert.That(NHibernateUtil.IsInitialized(turin.Settings), Is.False);
+
+ if (initialize)
+ {
+ using (var e = gavin.Settings.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+ using (var e = turin.Settings.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.True);
+ Assert.That(NHibernateUtil.IsInitialized(turin.Settings), Is.True);
+ Assert.That(gavin.Settings.Count, Is.EqualTo(5));
+ Assert.That(turin.Settings.Count, Is.EqualTo(10));
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ turin = s.Get("turin");
+ Assert.That(gavin.Settings.Count, Is.EqualTo(5));
+ Assert.That(turin.Settings.Count, Is.EqualTo(10));
+
+ t.Commit();
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public void ListInsertChildSaveChangeParent(bool initialize)
+ {
+ User gavin;
+ User turin;
+ var gavinItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ turin = new User("turin", "tiger");
+ s.Persist(gavin);
+ s.Persist(turin);
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new Company($"g{i}", i, gavin);
+ gavinItems.Add(item);
+ gavin.Companies.Add(item);
+
+ item = new Company($"t{i}", i, turin);
+ turin.Companies.Add(item);
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ turin = s.Get("turin");
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(turin.Companies.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+ Assert.That(NHibernateUtil.IsInitialized(turin.Companies), Is.False);
+
+ // Save companies and then add them to the collection
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ s.Save(item);
+ gavinItems.Add(item);
+ }
+
+ for (var i = 5; i < 10; i++)
+ {
+ if (i % 2 != 0)
+ {
+ gavin.Companies.Insert(i, gavinItems[i]);
+ }
+ else
+ {
+ gavin.Companies.Add(gavinItems[i]);
+ }
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Add companies to the collection and then save them
+ Sfi.Statistics.Clear();
+ for (var i = 10; i < 15; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ if (i % 2 != 0)
+ {
+ gavin.Companies.Insert(i, item);
+ }
+ else
+ {
+ gavin.Companies.Add(item);
+ }
+
+ gavinItems.Add(item);
+ s.Save(item);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Remove added items from the collection and add them to a different parent
+ foreach (var item in gavinItems.Skip(5).Take(5))
+ {
+ gavin.Companies.RemoveAt(5);
+
+ item.Owner = turin;
+ turin.Companies.Insert(item.ListIndex, item);
+ }
+
+ // Remove added items from the collection
+ for (var i = 10; i < 15; i++)
+ {
+ var item = gavinItems[i];
+ gavin.Companies.RemoveAt(5);
+ // When identity is used for the primary key the item will be already inserted in the database,
+ // so the RemoveAt method will mark it as an orphan which will be deleted on flush.
+ // The same would work for an initialized collection as the collection snapshot would contain the item.
+ // When dealing with an id generator that supports a delayed insert, we have to trigger a delete
+ // for the item as it is currently scheduled for insertion.
+ if (IsNativeIdentityGenerator)
+ {
+ if (i % 2 != 0)
+ {
+ item.Owner = null;
+ }
+ }
+ else
+ {
+ s.Delete(item);
+ }
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(turin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+ Assert.That(NHibernateUtil.IsInitialized(turin.Companies), Is.False);
+
+ if (initialize)
+ {
+ using (var e = gavin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+ using (var e = turin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+ Assert.That(NHibernateUtil.IsInitialized(turin.Companies), Is.True);
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(turin.Companies.Count, Is.EqualTo(10));
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ turin = s.Get("turin");
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(turin.Companies.Count, Is.EqualTo(10));
+
+ t.Commit();
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public void ListClearChildSaveChangeParent(bool initialize)
+ {
+ User gavin;
+ User turin;
+ var gavinItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ turin = new User("turin", "tiger");
+ s.Persist(gavin);
+ s.Persist(turin);
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new CreditCard($"g{i}", i, gavin);
+ gavin.CreditCards.Add(item);
+
+ item = new CreditCard($"t{i}", i, turin);
+ turin.CreditCards.Add(item);
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ turin = s.Get("turin");
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.CreditCards.Count, Is.EqualTo(5));
+ Assert.That(turin.CreditCards.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.CreditCards), Is.False);
+ Assert.That(NHibernateUtil.IsInitialized(turin.CreditCards), Is.False);
+
+ Sfi.Statistics.Clear();
+ gavin.CreditCards.Clear();
+ turin.CreditCards.Clear();
+ Assert.That(gavin.CreditCards.Count, Is.EqualTo(0));
+ Assert.That(turin.CreditCards.Count, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.CreditCards), Is.False);
+ Assert.That(NHibernateUtil.IsInitialized(turin.CreditCards), Is.False);
+
+ // Save credit cards and then add them to the collection
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new CreditCard($"c2{i}", i, gavin);
+ s.Save(item);
+ gavinItems.Add(item);
+ }
+
+ for (var i = 0; i < 5; i++)
+ {
+ gavin.CreditCards.Add(gavinItems[i]);
+ }
+
+ Assert.That(gavin.CreditCards.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.CreditCards), Is.False);
+
+ // Add credit cards to the collection and then save them
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ var item = new CreditCard($"c2{i}", i, gavin);
+ Assert.That(((IList) gavin.CreditCards).Add(item), Is.EqualTo(i));
+ gavinItems.Add(item);
+ s.Save(item);
+ }
+
+ Assert.That(gavin.CreditCards.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.CreditCards), Is.False);
+
+ // Remove added items from the collection and add them to a different parent
+ foreach (var item in gavinItems.Take(5))
+ {
+ gavin.CreditCards.Remove(item);
+
+ item.Owner = turin;
+ item.ListIndex += 5;
+ turin.CreditCards.Add(item);
+ }
+
+ Assert.That(gavin.CreditCards.Count, Is.EqualTo(5));
+ Assert.That(turin.CreditCards.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.CreditCards), Is.False);
+ Assert.That(NHibernateUtil.IsInitialized(turin.CreditCards), Is.False);
+
+ if (initialize)
+ {
+ using (var e = gavin.CreditCards.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+ using (var e = turin.CreditCards.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.CreditCards), Is.True);
+ Assert.That(NHibernateUtil.IsInitialized(turin.CreditCards), Is.True);
+ Assert.That(gavin.CreditCards.Count, Is.EqualTo(5));
+ Assert.That(turin.CreditCards.Count, Is.EqualTo(5));
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ turin = s.Get("turin");
+ Assert.That(gavin.CreditCards.Count, Is.EqualTo(10));
+ Assert.That(turin.CreditCards.Count, Is.EqualTo(10));
+
+ t.Commit();
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public void ListAddChildSaveChangeParent(bool initialize)
+ {
+ User gavin;
+ User turin;
+ var gavinItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ turin = new User("turin", "tiger");
+ s.Persist(gavin);
+ s.Persist(turin);
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new Company($"g{i}", i, gavin);
+ gavinItems.Add(item);
+ gavin.Companies.Add(item);
+
+ item = new Company($"t{i}", i, turin);
+ turin.Companies.Add(item);
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ turin = s.Get("turin");
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(turin.Companies.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+ Assert.That(NHibernateUtil.IsInitialized(turin.Companies), Is.False);
+
+ // Save companies and then add them to the collection
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ s.Save(item);
+ gavinItems.Add(item);
+ }
+
+ for (var i = 5; i < 10; i++)
+ {
+ gavin.Companies.Add(gavinItems[i]);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Add companies to the collection and then save them
+ Sfi.Statistics.Clear();
+ for (var i = 10; i < 15; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ Assert.That(((IList) gavin.Companies).Add(item), Is.EqualTo(i));
+ gavinItems.Add(item);
+ s.Save(item);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Remove added items from the collection and add them to a different parent
+ foreach (var item in gavinItems.Skip(5).Take(5))
+ {
+ gavin.Companies.Remove(item);
+
+ item.Owner = turin;
+ turin.Companies.Add(item);
+ }
+
+ // Remove added items from the collection
+ for (var i = 10; i < 15; i++)
+ {
+ var item = gavinItems[i];
+ gavin.Companies.Remove(item);
+ // When identity is used for the primary key the item will be already inserted in the database,
+ // so the RemoveAt method will mark it as an orphan which will be deleted on flush.
+ // The same would work for an initialized collection as the collection snapshot would contain the item.
+ // When dealing with an id generator that supports a delayed insert, we have to trigger a delete
+ // for the item as it is currently scheduled for insertion.
+ if (IsNativeIdentityGenerator)
+ {
+ if (i % 2 != 0)
+ {
+ item.Owner = null;
+ }
+ }
+ else
+ {
+ s.Delete(item);
+ }
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(turin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+ Assert.That(NHibernateUtil.IsInitialized(turin.Companies), Is.False);
+
+ if (initialize)
+ {
+ using (var e = gavin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+ using (var e = turin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+ Assert.That(NHibernateUtil.IsInitialized(turin.Companies), Is.True);
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(turin.Companies.Count, Is.EqualTo(10));
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ turin = s.Get("turin");
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(turin.Companies.Count, Is.EqualTo(10));
+
+ t.Commit();
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public void ListAddChildSave(bool initialize)
+ {
+ User gavin;
+ var gavinItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ s.Persist(gavin);
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new Company($"g{i}", i, gavin);
+ gavinItems.Add(item);
+ gavin.Companies.Add(item);
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+
+ Sfi.Statistics.Clear();
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Save companies and then add them to the collection
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ s.Save(item);
+ gavinItems.Add(item);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(IsNativeIdentityGenerator ? 10 : 5));
+
+ for (var i = 5; i < 10; i++)
+ {
+ gavin.Companies.Add(gavinItems[i]);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Add companies to the collection and then save them
+ Sfi.Statistics.Clear();
+ for (var i = 10; i < 15; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ Assert.That(((IList) gavinItems).Add(item), Is.EqualTo(i));
+ gavin.Companies.Add(item);
+ s.Save(item);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ if (initialize)
+ {
+ using (var e = gavin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ t.Commit();
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public void ListAdd(bool initialize)
+ {
+ User gavin;
+ var addedItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ s.Persist(gavin);
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Add(item);
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Test adding companies with ICollection interface
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Add(item);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Test adding companies with IList interface
+ Sfi.Statistics.Clear();
+ for (var i = 10; i < 15; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ Assert.That(((IList)addedItems).Add(item), Is.EqualTo(i));
+ gavin.Companies.Add(item);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+
+ // Check existance of added companies
+ Sfi.Statistics.Clear();
+ foreach (var item in addedItems.Skip(5))
+ {
+ Assert.That(gavin.Companies.Contains(item), Is.True);
+ }
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Check existance of not loaded companies
+ Assert.That(gavin.Companies.Contains(addedItems[0]), Is.True);
+ Assert.That(gavin.Companies.Contains(addedItems[1]), Is.True);
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Check existance of not existing companies
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Companies.Contains(new Company("test1", 15, gavin)), Is.False);
+ Assert.That(gavin.Companies.Contains(new Company("test2", 16, gavin)), Is.False);
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ if (initialize)
+ {
+ using (var e = gavin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ t.Commit();
+ }
+ }
+
+ [TestCase(false, false)]
+ [TestCase(false, true)]
+ [TestCase(true, false)]
+ [TestCase(true, true)]
+ public void ListAddDuplicated(bool initialize, bool flush)
+ {
+ User gavin;
+ var addedItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ s.Persist(gavin);
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Add(item);
+ gavin.Companies.Add(item);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ // Refresh added items
+ for (var i = 0; i < 5; i++)
+ {
+ addedItems[i] = s.Get(addedItems[i].Id);
+ }
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Readd items
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ gavin.Companies.Add(addedItems[i]);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ if (flush)
+ {
+ s.Flush();
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+ }
+
+ if (initialize)
+ {
+ using (var e = gavin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+ Assert.That(gavin.Companies.Count, Is.EqualTo(flush ? 5 : 10));
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ t.Commit();
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public void ListInsert(bool initialize)
+ {
+ User gavin;
+ var addedItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ s.Persist(gavin);
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Add(item);
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Test inserting companies at the start
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Insert(0, item);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Test inserting companies at the end
+ Sfi.Statistics.Clear();
+ for (var i = 10; i < 15; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Insert(i, item);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Try insert invalid indexes
+ Assert.Throws(() => gavin.Companies.RemoveAt(-1));
+ Assert.Throws(() => gavin.Companies.RemoveAt(20));
+
+ // Check existance of added companies
+ Sfi.Statistics.Clear();
+ foreach (var item in addedItems.Skip(5))
+ {
+ Assert.That(gavin.Companies.Contains(item), Is.True);
+ }
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Check existance of not loaded companies
+ Assert.That(gavin.Companies.Contains(addedItems[0]), Is.True);
+ Assert.That(gavin.Companies.Contains(addedItems[1]), Is.True);
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Check existance of not existing companies
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Companies.Contains(new Company("test1", 15, gavin)), Is.False);
+ Assert.That(gavin.Companies.Contains(new Company("test2", 16, gavin)), Is.False);
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ if (initialize)
+ {
+ using (var e = gavin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ t.Commit();
+ }
+ }
+
+ [TestCase(false, false)]
+ [TestCase(false, true)]
+ [TestCase(true, false)]
+ [TestCase(true, true)]
+ public void ListInsertDuplicated(bool initialize, bool flush)
+ {
+ User gavin;
+ var addedItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ s.Persist(gavin);
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Insert(i, item);
+ gavin.Companies.Insert(i, item);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ // Refresh added items
+ for (var i = 0; i < 5; i++)
+ {
+ addedItems[i] = s.Get(addedItems[i].Id);
+ }
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Readd items
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ gavin.Companies.Insert(4 - i, addedItems[i]);
+ }
+
+ Assert.That(gavin.Companies[0].ListIndex, Is.EqualTo(4));
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ if (flush)
+ {
+ s.Flush();
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+ }
+
+ if (initialize)
+ {
+ using (var e = gavin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+ Assert.That(gavin.Companies.Count, Is.EqualTo(flush ? 5 : 10));
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ t.Commit();
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public void ListRemoveAt(bool initialize)
+ {
+ User gavin;
+ var addedItems = new List();
+ var finalIndexOrder = new List {0, 1, 2, 6, 8, 9};
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ s.Persist(gavin);
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Add(item);
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ // Refresh added items
+ for (var i = 0; i < 5; i++)
+ {
+ addedItems[i] = s.Get(addedItems[i].Id);
+ }
+
+ // Add transient companies
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Insert(i, item);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Remove transient companies
+ Sfi.Statistics.Clear();
+ gavin.Companies.RemoveAt(5);
+ gavin.Companies.RemoveAt(6);
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(8));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Remove persisted companies
+ Sfi.Statistics.Clear();
+ gavin.Companies.RemoveAt(3);
+ gavin.Companies.RemoveAt(3);
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(6));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Try remove invalid indexes
+ Assert.Throws(() => gavin.Companies.RemoveAt(-1));
+ Assert.Throws(() => gavin.Companies.RemoveAt(8));
+
+ // Check existance of companies
+ Sfi.Statistics.Clear();
+ var removedIndexes = new HashSet {3, 4, 5, 7};
+ for (var i = 0; i < addedItems.Count; i++)
+ {
+ Assert.That(
+ gavin.Companies.Contains(addedItems[i]),
+ removedIndexes.Contains(i) ? Is.False : (IResolveConstraint) Is.True,
+ $"Element at index {i} was {(removedIndexes.Contains(i) ? "not " : "")}removed");
+ }
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(3));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Check existance of not existing companies
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Companies.Contains(new Company("test1", 15, gavin)), Is.False);
+ Assert.That(gavin.Companies.Contains(new Company("test2", 16, gavin)), Is.False);
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ gavin.UpdateCompaniesIndexes();
+
+ if (initialize)
+ {
+ using (var e = gavin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+ Assert.That(gavin.Companies.Count, Is.EqualTo(6));
+ Assert.That(gavin.Companies.Select(o => o.OriginalIndex), Is.EquivalentTo(finalIndexOrder));
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ Assert.That(gavin.Companies.Count, Is.EqualTo(6));
+ Assert.That(gavin.Companies.Select(o => o.OriginalIndex), Is.EquivalentTo(finalIndexOrder));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+
+ t.Commit();
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public void ListGetSet(bool initialize)
+ {
+ User gavin;
+ var addedItems = new List();
+ var finalIndexOrder = new List {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ s.Persist(gavin);
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Add(item);
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ // Refresh added items
+ for (var i = 0; i < 5; i++)
+ {
+ addedItems[i] = s.Get(addedItems[i].Id);
+ }
+
+ // Add transient companies
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Insert(i, item);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Compare all items
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 10; i++)
+ {
+ Assert.That(gavin.Companies[i], Is.EqualTo(addedItems[i]));
+ }
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Try get invalid indexes
+ Assert.Throws(() =>
+ {
+ var item = gavin.Companies[10];
+ });
+ Assert.Throws(() =>
+ {
+ var item = gavin.Companies[-1];
+ });
+
+ // Try set invalid indexes
+ Assert.Throws(() => gavin.Companies[10] = addedItems[0]);
+ Assert.Throws(() => gavin.Companies[-1] = addedItems[0]);
+
+ // Swap transient and persisted indexes
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ var hiIndex = 9 - i;
+ var tmp = gavin.Companies[i];
+ gavin.Companies[i] = gavin.Companies[hiIndex];
+ gavin.Companies[hiIndex] = tmp;
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(10));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Check indexes
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 10; i++)
+ {
+ Assert.That(gavin.Companies[i].ListIndex, Is.EqualTo(finalIndexOrder[i]));
+ }
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ gavin.UpdateCompaniesIndexes();
+
+ if (initialize)
+ {
+ using (var e = gavin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(gavin.Companies.Select(o => o.OriginalIndex), Is.EquivalentTo(finalIndexOrder));
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(gavin.Companies.Select(o => o.OriginalIndex), Is.EquivalentTo(finalIndexOrder));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+
+ t.Commit();
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public void ListFlush(bool initialize)
+ {
+ User gavin;
+ var addedItems = new List();
+ var finalIndexOrder = Enumerable.Range(0, 13).ToList();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ s.Persist(gavin);
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Add(item);
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ // Refresh added items
+ for (var i = 0; i < 5; i++)
+ {
+ addedItems[i] = s.Get(addedItems[i].Id);
+ }
+
+ // Add transient companies with Add
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Add(item);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Add transient companies with Insert
+ Sfi.Statistics.Clear();
+ using (var sqlLog = new SqlLogSpy())
+ {
+ for (var i = 10; i < 15; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Insert(i, item);
+ }
+
+ Assert.That(FindAllOccurrences(sqlLog.GetWholeLog(), "INSERT \n INTO"), Is.EqualTo(5));
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Add transient companies with Add
+ Sfi.Statistics.Clear();
+ for (var i = 15; i < 20; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.Companies.Add(item);
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(20));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Remove last 5 transient companies
+ Sfi.Statistics.Clear();
+ using (var sqlLog = new SqlLogSpy())
+ {
+ for (var i = 15; i < 20; i++)
+ {
+ Assert.That(gavin.Companies.Remove(addedItems[i]), Is.True);
+ }
+
+ Assert.That(FindAllOccurrences(sqlLog.GetWholeLog(), "INSERT \n INTO"), Is.EqualTo(10));
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Remove last 5 transient companies
+ Sfi.Statistics.Clear();
+ using (var sqlLog = new SqlLogSpy())
+ {
+ for (var i = 10; i < 15; i++)
+ {
+ gavin.Companies.RemoveAt(10);
+ }
+
+ Assert.That(FindAllOccurrences(sqlLog.GetWholeLog(), "DELETE \n FROM"), Is.EqualTo(5));
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(1));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(7));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Add transient companies with Add
+ Sfi.Statistics.Clear();
+ for (var i = 10; i < 15; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ addedItems[i] = item;
+ Assert.That(((IList)gavin.Companies).Add(item), Is.EqualTo(i));
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Remove last transient company
+ Sfi.Statistics.Clear();
+ using (var sqlLog = new SqlLogSpy())
+ {
+ Assert.That(gavin.Companies.Remove(addedItems[14]), Is.EqualTo(true));
+ var log = sqlLog.GetWholeLog();
+ Assert.That(FindAllOccurrences(log, "DELETE \n FROM"), Is.EqualTo(5));
+ Assert.That(FindAllOccurrences(log, "INSERT \n INTO"), Is.EqualTo(5));
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(14));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Test index getter
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Companies[0], Is.EqualTo(addedItems[0]));
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(14));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(1));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(3));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Remove last transient company
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Companies.Remove(addedItems[13]), Is.EqualTo(true));
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(13));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Test index setter
+ Sfi.Statistics.Clear();
+ gavin.Companies[0] = addedItems[0];
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(13));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(1));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(3));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Test manual flush after remove
+ Sfi.Statistics.Clear();
+ gavin.Companies.RemoveAt(12);
+ using (var sqlLog = new SqlLogSpy())
+ {
+ s.Flush();
+ Assert.That(FindAllOccurrences(sqlLog.GetWholeLog(), "DELETE \n FROM"), Is.EqualTo(1));
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(12));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ // Test manual flush after insert
+ Sfi.Statistics.Clear();
+ gavin.Companies.Add(new Company($"c{12}", 12, gavin));
+ using (var sqlLog = new SqlLogSpy())
+ {
+ s.Flush();
+ Assert.That(FindAllOccurrences(sqlLog.GetWholeLog(), "INSERT \n INTO"), Is.EqualTo(1));
+ }
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(13));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ for (var i = 0; i < gavin.Companies.Count; i++)
+ {
+ Assert.That(gavin.Companies[i].ListIndex, Is.EqualTo(i));
+ }
+
+ if (initialize)
+ {
+ using (var e = gavin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+ Assert.That(gavin.Companies.Count, Is.EqualTo(13));
+ Assert.That(gavin.Companies.Select(o => o.ListIndex), Is.EquivalentTo(finalIndexOrder));
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ Assert.That(gavin.Companies.Count, Is.EqualTo(13));
+ Assert.That(gavin.Companies.Select(o => o.ListIndex), Is.EquivalentTo(finalIndexOrder));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+
+ t.Commit();
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public void ListClear(bool initialize)
+ {
+ User gavin;
+ var addedItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ s.Persist(gavin);
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new CreditCard($"c{i}", i, gavin);
+ addedItems.Add(item);
+ gavin.CreditCards.Add(item);
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ s.FlushMode = FlushMode.Commit;
+
+ gavin = s.Get("gavin");
+ // Refresh added items
+ for (var i = 0; i < 5; i++)
+ {
+ addedItems[i] = s.Get(addedItems[i].Id);
+ }
+
+ var collection = gavin.CreditCards;
+
+ // Add transient permissions
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ var item = new CreditCard($"c{i}", i, gavin);
+ addedItems.Add(item);
+ collection.Insert(i, item);
+ }
+
+ Assert.That(collection.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ Sfi.Statistics.Clear();
+ collection.Clear();
+
+ Assert.That(collection.Count, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ // Readd two not loaded and two transient permissions
+ collection.Add(addedItems[0]);
+ collection.Add(addedItems[1]);
+ collection.Add(addedItems[5]);
+ collection.Add(addedItems[6]);
+
+ Assert.That(collection.Count, Is.EqualTo(4));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ // Remove one not loaded and one transient permissions
+ Assert.That(collection.Remove(addedItems[1]), Is.True);
+ Assert.That(collection.Remove(addedItems[6]), Is.True);
+
+ Assert.That(collection.Count, Is.EqualTo(2));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ // Remove not existing items
+ Assert.That(collection.Remove(addedItems[1]), Is.False);
+ Assert.That(collection.Remove(addedItems[6]), Is.False);
+
+ Assert.That(collection.Count, Is.EqualTo(2));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ if (initialize)
+ {
+ using (var e = collection.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.True);
+ Assert.That(collection.Count, Is.EqualTo(2));
+ }
+
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ var collection = gavin.CreditCards;
+ // As the cascade option is set to all, the clear operation will only work on
+ // transient permissions
+ Assert.That(collection.Count, Is.EqualTo(6));
+ for (var i = 0; i < 10; i++)
+ {
+ Assert.That(collection.Contains(addedItems[i]), i < 6 ? Is.True : (IResolveConstraint) Is.False);
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ t.Commit();
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public void ListIndexOperations(bool initialize)
+ {
+ User gavin;
+ var finalIndexOrder = new List {6, 0, 4};
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ s.Persist(gavin);
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new Company($"c{i}", i, gavin);
+ gavin.Companies.Add(item);
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ // Current tracker state:
+ // Indexes: 0,1,2,3,4
+ // Queue: /
+ // RemoveDbIndexes: /
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Companies.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ Sfi.Statistics.Clear();
+ gavin.Companies.Insert(1, new Company("c5", 5, gavin));
+ // Current tracker state:
+ // Indexes: 0,5,1,2,3,4
+ // Queue: {1, 5}
+ // RemoveDbIndexes: /
+
+ gavin.Companies.Insert(0, new Company("c6", 6, gavin));
+ // Current tracker state:
+ // Indexes: 6,0,5,1,2,3,4
+ // Queue: {0, 6}, {2, 5}
+ // RemoveDbIndexes: /
+
+ gavin.Companies.RemoveAt(4);
+ // Current tracker state:
+ // Indexes: 6,0,5,1,3,4
+ // Queue: {0, 6}, {2, 5}
+ // RemoveDbIndexes: 2
+
+ gavin.Companies.RemoveAt(3);
+ // Current tracker state:
+ // Indexes: 6,0,5,3,4
+ // Queue: {0, 6}, {2, 5}
+ // RemoveDbIndexes: 1,2
+
+ gavin.Companies.RemoveAt(3);
+ // Current tracker state:
+ // Indexes: 6,0,5,4
+ // Queue: {0, 6}, {2, 5}
+ // RemoveDbIndexes: 1,2,3
+
+ gavin.Companies.RemoveAt(2);
+ // Current tracker state:
+ // Indexes: 6,0,4
+ // Queue: {0, 6}
+ // RemoveDbIndexes: 1,2,3
+
+ Assert.That(gavin.Companies.Count, Is.EqualTo(3));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(3));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.False);
+
+ gavin.UpdateCompaniesIndexes();
+
+ for (var i = 0; i < gavin.Companies.Count; i++)
+ {
+ Assert.That(gavin.Companies[i].OriginalIndex, Is.EqualTo(finalIndexOrder[i]));
+ }
+
+ if (initialize)
+ {
+ using (var e = gavin.Companies.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+ Assert.That(gavin.Companies.Count, Is.EqualTo(3));
+ Assert.That(gavin.Companies.Select(o => o.OriginalIndex), Is.EquivalentTo(finalIndexOrder));
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ Assert.That(gavin.Companies.Count, Is.EqualTo(3));
+ Assert.That(gavin.Companies.Select(o => o.OriginalIndex), Is.EquivalentTo(finalIndexOrder));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Companies), Is.True);
+
+ t.Commit();
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public void SetAdd(bool initialize)
+ {
+ User gavin;
+ Document hia;
+ Document hia2;
+ var addedDocuments = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ hia = new Document("HiA", "blah blah blah", gavin);
+ hia2 = new Document("HiA2", "blah blah blah blah", gavin);
+ gavin.Documents.Add(hia);
+ gavin.Documents.Add(hia2);
+ s.Persist(gavin);
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Documents.Count, Is.EqualTo(2));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Test adding documents with ISet interface
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ var document = new Document($"document{i}", $"content{i}", gavin);
+ addedDocuments.Add(document);
+ Assert.That(gavin.Documents.Add(document), Is.True);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(7));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Test adding documents with ICollection interface
+ Sfi.Statistics.Clear();
+ var documents = (ICollection) gavin.Documents;
+ for (var i = 0; i < 5; i++)
+ {
+ var document = new Document($"document2{i}", $"content{i}", gavin);
+ addedDocuments.Add(document);
+ documents.Add(document);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(12));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ // In this case we cannot determine whether the entities are transient or not so
+ // we are forced to check the database
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Test readding documents with ISet interface
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ Assert.That(gavin.Documents.Add(addedDocuments[i]), Is.False);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(12));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Test readding documents with ICollection interface
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ documents.Add(addedDocuments[i]);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(12));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Check existance of added documents
+ Sfi.Statistics.Clear();
+ foreach (var document in addedDocuments)
+ {
+ Assert.That(gavin.Documents.Contains(document), Is.True);
+ }
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Check existance of not loaded documents
+ Assert.That(gavin.Documents.Contains(hia), Is.True);
+ Assert.That(gavin.Documents.Contains(hia2), Is.True);
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Check existance of not existing documents
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Documents.Contains(new Document("test1", "content", gavin)), Is.False);
+ Assert.That(gavin.Documents.Contains(new Document("test2", "content", gavin)), Is.False);
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Test adding not loaded documents
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Documents.Add(hia), Is.False);
+ documents.Add(hia);
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(12));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ if (initialize)
+ {
+ using (var e = gavin.Documents.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.True);
+ Assert.That(gavin.Documents.Count, Is.EqualTo(12));
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ Assert.That(gavin.Documents.Count, Is.EqualTo(12));
+ Assert.That(gavin.Documents.Contains(hia2), Is.True);
+ Assert.That(gavin.Documents.Contains(hia), Is.True);
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ t.Commit();
+ }
+ }
+
+ [TestCase(false, false)]
+ [TestCase(false, true)]
+ [TestCase(true, false)]
+ [TestCase(true, true)]
+ public void SetAddDuplicated(bool initialize, bool flush)
+ {
+ User gavin;
+ var addedItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ s.Persist(gavin);
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new Document($"d{i}", $"c{i}", gavin);
+ addedItems.Add(item);
+ gavin.Documents.Add(item);
+ gavin.Documents.Add(item);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(5));
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ // Refresh added items
+ for (var i = 0; i < 5; i++)
+ {
+ addedItems[i] = s.Get(addedItems[i].Title);
+ }
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Documents.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Readd items
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ Assert.That(gavin.Documents.Add(addedItems[i]), Is.False);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ if (flush)
+ {
+ s.Flush();
+ Assert.That(gavin.Documents.Count, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+ }
+
+ if (initialize)
+ {
+ using (var e = gavin.Documents.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.True);
+ Assert.That(gavin.Documents.Count, Is.EqualTo(5));
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ Assert.That(gavin.Documents.Count, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ t.Commit();
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public void SetAddTransient(bool initialize)
+ {
+ User gavin;
+ var addedItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ s.Persist(gavin);
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new UserPermission($"p{i}", gavin);
+ addedItems.Add(item);
+ gavin.Permissions.Add(item);
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ s.FlushMode = FlushMode.Commit;
+
+ gavin = s.Get("gavin");
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Permissions.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Permissions), Is.False);
+
+ // Test adding permissions with ICollection interface
+ Sfi.Statistics.Clear();
+ var items = (ICollection) gavin.Permissions;
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new UserPermission($"p2{i}", gavin);
+ addedItems.Add(item);
+ items.Add(item);
+ }
+
+ Assert.That(gavin.Permissions.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Permissions), Is.False);
+
+ // Test readding permissions with ICollection interface
+ Sfi.Statistics.Clear();
+ foreach (var item in addedItems.Skip(5))
+ {
+ items.Add(item);
+ }
+
+ Assert.That(gavin.Permissions.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Permissions), Is.False);
+
+ // Test adding not loaded permissions with ICollection interface
+ Sfi.Statistics.Clear();
+ foreach (var item in addedItems.Take(5))
+ {
+ items.Add(item);
+ }
+
+ Assert.That(gavin.Permissions.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Permissions), Is.False);
+
+ // Test adding loaded permissions with ICollection interface
+ Sfi.Statistics.Clear();
+ foreach (var item in s.Query())
+ {
+ items.Add(item);
+ }
+
+ Assert.That(gavin.Permissions.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(6));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Permissions), Is.False);
+
+
+ // Test adding permissions with ISet interface
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new UserPermission($"p3{i}", gavin);
+ addedItems.Add(item);
+ gavin.Permissions.Add(item);
+ }
+
+ Assert.That(gavin.Permissions.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Permissions), Is.False);
+
+ // Test readding permissions with ISet interface
+ Sfi.Statistics.Clear();
+ foreach (var item in addedItems.Skip(10))
+ {
+ gavin.Permissions.Add(item);
+ }
+
+ Assert.That(gavin.Permissions.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Permissions), Is.False);
+
+ // Test adding not loaded permissions with ISet interface
+ Sfi.Statistics.Clear();
+ foreach (var item in addedItems.Take(5))
+ {
+ gavin.Permissions.Add(item);
+ }
+
+ Assert.That(gavin.Permissions.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Permissions), Is.False);
+
+ // Test adding loaded permissions with ISet interface
+ Sfi.Statistics.Clear();
+ foreach (var item in s.Query())
+ {
+ gavin.Permissions.Add(item);
+ }
+
+ Assert.That(gavin.Permissions.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(6));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Permissions), Is.False);
+
+ if (initialize)
+ {
+ using (var e = gavin.Permissions.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Permissions), Is.True);
+ Assert.That(gavin.Permissions.Count, Is.EqualTo(15));
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ Assert.That(gavin.Permissions.Count, Is.EqualTo(15));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Permissions), Is.False);
+
+ t.Commit();
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public void SetRemove(bool initialize)
+ {
+ User gavin;
+ var addedDocuments = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ for (var i = 0; i < 5; i++)
+ {
+ var document = new Document($"document{i}", $"content{i}", gavin);
+ addedDocuments.Add(document);
+ gavin.Documents.Add(document);
+ }
+
+ s.Persist(gavin);
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ // Refresh added items
+ for (var i = 0; i < 5; i++)
+ {
+ addedDocuments[i] = s.Get(addedDocuments[i].Title);
+ }
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Documents.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Add new documents
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ var document = new Document($"document2{i}", $"content{i}", gavin);
+ addedDocuments.Add(document);
+ ((ICollection)gavin.Documents).Add(document);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Test removing existing documents
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ Assert.That(gavin.Documents.Remove(addedDocuments[i]), Is.True);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Test removing removed existing documents
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ Assert.That(gavin.Documents.Contains(addedDocuments[i]), Is.False);
+ Assert.That(gavin.Documents.Remove(addedDocuments[i]), Is.False);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Test removing not existing documents
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ var document = new Document($"test{i}", "content", gavin);
+ Assert.That(gavin.Documents.Remove(document), Is.False);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Test removing newly added documents
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ Assert.That(gavin.Documents.Contains(addedDocuments[i]), Is.True);
+ Assert.That(gavin.Documents.Remove(addedDocuments[i]), Is.True);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Test removing removed newly added documents
+ Sfi.Statistics.Clear();
+ for (var i = 5; i < 10; i++)
+ {
+ Assert.That(gavin.Documents.Contains(addedDocuments[i]), Is.False);
+ Assert.That(gavin.Documents.Remove(addedDocuments[i]), Is.False);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ // Test removing not existing documents
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ var document = new Document($"test{i}", "content", gavin);
+ Assert.That(gavin.Documents.Remove(document), Is.False);
+ }
+
+ Assert.That(gavin.Documents.Count, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ if (initialize)
+ {
+ using (var e = gavin.Documents.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.True);
+ Assert.That(gavin.Documents.Count, Is.EqualTo(0));
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ Assert.That(gavin.Documents.Count, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Documents), Is.False);
+
+ t.Commit();
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public void SetClear(bool initialize)
+ {
+ User gavin;
+ var addedItems = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ s.Persist(gavin);
+
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new UserPermission($"p{i}", gavin);
+ addedItems.Add(item);
+ gavin.Permissions.Add(item);
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ s.FlushMode = FlushMode.Commit;
+
+ gavin = s.Get("gavin");
+ // Refresh added items
+ for (var i = 0; i < 5; i++)
+ {
+ addedItems[i] = s.Get(addedItems[i].Id);
+ }
+
+ var collection = gavin.Permissions;
+
+ Sfi.Statistics.Clear();
+ Assert.That(collection.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ // Add transient permissions
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ var item = new UserPermission($"p2{i}", gavin);
+ addedItems.Add(item);
+ collection.Add(item);
+ }
+
+ Assert.That(collection.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ Sfi.Statistics.Clear();
+ collection.Clear();
+
+ Assert.That(collection.Count, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ // Readd two not loaded and two transient permissions
+ Assert.That(collection.Add(addedItems[0]), Is.True);
+ Assert.That(collection.Add(addedItems[1]), Is.True);
+ Assert.That(collection.Add(addedItems[5]), Is.True);
+ Assert.That(collection.Add(addedItems[6]), Is.True);
+
+ Assert.That(collection.Count, Is.EqualTo(4));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ // Remove one not loaded and one transient permissions
+ Assert.That(collection.Remove(addedItems[1]), Is.True);
+ Assert.That(collection.Remove(addedItems[6]), Is.True);
+
+ Assert.That(collection.Count, Is.EqualTo(2));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ // Remove not existing items
+ Assert.That(collection.Remove(addedItems[1]), Is.False);
+ Assert.That(collection.Remove(addedItems[6]), Is.False);
+
+ Assert.That(collection.Count, Is.EqualTo(2));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ if (initialize)
+ {
+ using (var e = collection.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.True);
+ Assert.That(collection.Count, Is.EqualTo(2));
+ }
+
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+ var collection = gavin.Permissions;
+ // As the cascade option is set to all, the clear operation will only work on
+ // transient permissions
+ Assert.That(collection.Count, Is.EqualTo(6));
+ for (var i = 0; i < 10; i++)
+ {
+ Assert.That(collection.Contains(addedItems[i]), i < 6 ? Is.True : (IResolveConstraint) Is.False);
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(collection), Is.False);
+
+ t.Commit();
+ }
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public void MapAdd(bool initialize)
+ {
+ User gavin;
+ UserSetting setting;
+ var addedSettings = new List();
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = new User("gavin", "secret");
+ s.Persist(gavin);
+
+ for (var i = 0; i < 5; i++)
+ {
+ setting = new UserSetting($"s{i}", $"data{i}", gavin);
+ addedSettings.Add(setting);
+ gavin.Settings.Add(setting.Name, setting);
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get("gavin");
+
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Settings.Count, Is.EqualTo(5));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(1));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Test adding settings with Add method
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ setting = new UserSetting($"s2{i}", $"data{i}", gavin);
+ addedSettings.Add(setting);
+ gavin.Settings.Add(setting.Name, setting);
+ }
+
+ Assert.That(gavin.Settings.Count, Is.EqualTo(10));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Test adding settings with []
+ Sfi.Statistics.Clear();
+ for (var i = 0; i < 5; i++)
+ {
+ setting = new UserSetting($"s3{i}", $"data{i}", gavin);
+ addedSettings.Add(setting);
+
+ gavin.Settings[setting.Name] = setting;
+ }
+
+ Assert.That(gavin.Settings.Count, Is.EqualTo(15));
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Check existance of added settings
+ Sfi.Statistics.Clear();
+ foreach (var item in addedSettings.Skip(5))
+ {
+ Assert.That(gavin.Settings.ContainsKey(item.Name), Is.True);
+ Assert.That(gavin.Settings.Contains(new KeyValuePair(item.Name, item)), Is.True);
+ }
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Check existance of not loaded settings
+ foreach (var item in addedSettings.Take(5))
+ {
+ Assert.That(gavin.Settings.ContainsKey(item.Name), Is.True);
+ }
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(5));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Check existance of not existing settings
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Settings.ContainsKey("test"), Is.False);
+ Assert.That(gavin.Settings.ContainsKey("test2"), Is.False);
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Try to add an existing setting
+ Assert.Throws(() => gavin.Settings.Add("s0", new UserSetting("s0", "data", gavin)));
+ Assert.Throws(() => gavin.Settings.Add("s20", new UserSetting("s20", "data", gavin)));
+ Assert.Throws(() => gavin.Settings.Add("s30", new UserSetting("s30", "data", gavin)));
+
+ // Get values of not loaded keys
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Settings.TryGetValue("s0", out setting), Is.True);
+ Assert.That(setting.Id, Is.EqualTo(addedSettings[0].Id));
+ Assert.That(gavin.Settings["s0"].Id, Is.EqualTo(addedSettings[0].Id));
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(2));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Get values of newly added keys
+ Sfi.Statistics.Clear();
+ Assert.That(gavin.Settings.TryGetValue("s20", out setting), Is.True);
+ Assert.That(setting, Is.EqualTo(addedSettings[5]));
+ Assert.That(gavin.Settings["s20"], Is.EqualTo(addedSettings[5]));
+ Assert.That(gavin.Settings.TryGetValue("s30", out setting), Is.True);
+ Assert.That(setting, Is.EqualTo(addedSettings[10]));
+ Assert.That(gavin.Settings["s30"], Is.EqualTo(addedSettings[10]));
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ // Try to get a non existing setting
+ Assert.That(gavin.Settings.TryGetValue("test", out setting), Is.False);
+ Assert.That(gavin.Settings.TryGetValue("test2", out setting), Is.False);
+ Assert.Throws(() =>
+ {
+ setting = gavin.Settings["test"];
+ });
+ Assert.Throws(() =>
+ {
+ setting = gavin.Settings["test2"];
+ });
+
+ Assert.That(Sfi.Statistics.FlushCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(4));
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.False);
+
+ if (initialize)
+ {
+ using (var e = gavin.Settings.GetEnumerator())
+ {
+ e.MoveNext();
+ }
+
+ Assert.That(NHibernateUtil.IsInitialized(gavin.Settings), Is.True);
+ Assert.That(gavin.Settings.Count, Is.EqualTo(15));
+ }
+
+ t.Commit();
+ }
+
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ gavin = s.Get