diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH3848/CriteriaTestFixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH3848/CriteriaTestFixture.cs
new file mode 100644
index 00000000000..3955fe3e783
--- /dev/null
+++ b/src/NHibernate.Test/Async/NHSpecificTest/NH3848/CriteriaTestFixture.cs
@@ -0,0 +1,221 @@
+//------------------------------------------------------------------------------
+//
+// 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.Collections.Generic;
+using NHibernate.Criterion;
+using NHibernate.SqlCommand;
+using NHibernate.Transform;
+
+namespace NHibernate.Test.NHSpecificTest.NH3848
+{
+ using System.Threading.Tasks;
+ using System.Threading;
+ public class CriteriaTestFixtureAsync : FixtureAsync
+ {
+ protected override Task> GetCustomersWithOrdersEagerLoadedAsync(ISession session, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ try
+ {
+ return
+ session
+ .CreateCriteria()
+ .Fetch("Orders")
+ .SetResultTransformer(new DistinctRootEntityResultTransformer())
+ .ListAsync(cancellationToken);
+ }
+ catch (System.Exception ex)
+ {
+ return Task.FromException>(ex);
+ }
+ }
+
+ protected override Task> GetCustomersByOrderNumberUsingOnClauseAsync(ISession session, int orderNumber, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ try
+ {
+ return
+ session
+ .CreateCriteria()
+ .CreateAlias("Orders", "order", JoinType.LeftOuterJoin, Restrictions.Eq("Number", orderNumber))
+ .ListAsync(cancellationToken);
+ }
+ catch (System.Exception ex)
+ {
+ return Task.FromException>(ex);
+ }
+ }
+
+ protected override Task> GetCustomersByOrderNumberUsingFetchAsync(ISession session, int orderNumber, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ try
+ {
+ return
+ session
+ .CreateCriteria()
+ .CreateAlias("Orders", "order", JoinType.InnerJoin, Restrictions.Eq("Number", orderNumber))
+ .Fetch(SelectMode.Fetch, "Orders")
+ .ListAsync(cancellationToken);
+ }
+ catch (System.Exception ex)
+ {
+ return Task.FromException>(ex);
+ }
+ }
+
+ protected override Task> GetCustomersByOrderNumberUsingFetchAndWhereClauseAsync(ISession session, int orderNumber, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ try
+ {
+ return
+ session
+ .CreateCriteria()
+ .Fetch(SelectMode.Fetch, "Orders")
+ .CreateCriteria("Orders", JoinType.InnerJoin)
+ .Add(Restrictions.Eq("Number", orderNumber))
+ .ListAsync(cancellationToken);
+ }
+ catch (System.Exception ex)
+ {
+ return Task.FromException>(ex);
+ }
+ }
+
+ protected override Task> GetCustomersAndCompaniesByOrderNumberUsingFetchAndWhereClauseAsync(ISession session, int orderNumber, string name, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ try
+ {
+ return
+ session
+ .CreateCriteria()
+ .CreateAlias("Orders", "order", JoinType.InnerJoin, Restrictions.Eq("Number", orderNumber))
+ .Fetch(SelectMode.Fetch, "Orders")
+ .CreateAlias("Companies", "company", JoinType.LeftOuterJoin, Restrictions.Eq("Name", name))
+ .ListAsync(cancellationToken);
+ }
+ catch (System.Exception ex)
+ {
+ return Task.FromException>(ex);
+ }
+ }
+
+ protected override Task> GetCustomersAndCompaniesByOrderNumberUsingFetchWithoutRestrictionsAsync(ISession session, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ try
+ {
+ return
+ session
+ .CreateCriteria()
+ .Fetch(SelectMode.Fetch, "Orders")
+ .CreateAlias("Orders", "order", JoinType.InnerJoin)
+ .CreateAlias("Companies", "company", JoinType.LeftOuterJoin)
+ .ListAsync(cancellationToken);
+ }
+ catch (System.Exception ex)
+ {
+ return Task.FromException>(ex);
+ }
+ }
+
+ protected override Task> GetCustomersWithCompaniesByOrderNumberUsingOnClauseAsync(
+ ISession session,
+ int orderNumber, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ try
+ {
+ return
+ session
+ .CreateCriteria()
+ .CreateAlias("Orders", "order", JoinType.LeftOuterJoin, Restrictions.Eq("Number", orderNumber))
+ .CreateAlias("Companies", "company", JoinType.LeftOuterJoin)
+ .ListAsync(cancellationToken);
+ }
+ catch (System.Exception ex)
+ {
+ return Task.FromException>(ex);
+ }
+ }
+
+ protected override Task> GetCustomersByOrderNumberUsingWhereClauseAsync(ISession session, int orderNumber, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ try
+ {
+ return
+ session
+ .CreateCriteria()
+ .CreateCriteria("Orders", "Order", JoinType.LeftOuterJoin)
+ .Add(Restrictions.Eq("Number", orderNumber))
+ .SetResultTransformer(new DistinctRootEntityResultTransformer())
+ .ListAsync(cancellationToken);
+ }
+ catch (System.Exception ex)
+ {
+ return Task.FromException>(ex);
+ }
+ }
+
+ protected override Task> GetCustomersByNameUsingWhereClauseAsync(ISession session, string customerName, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ try
+ {
+ return
+ session
+ .CreateCriteria()
+ .CreateAlias("Orders", "order", JoinType.LeftOuterJoin)
+ .Add(Restrictions.Eq("Name", "First Customer"))
+ .SetResultTransformer(new DistinctRootEntityResultTransformer())
+ .ListAsync(cancellationToken);
+ }
+ catch (System.Exception ex)
+ {
+ return Task.FromException>(ex);
+ }
+ }
+
+ protected override Task> GetCustomersByOrderNumberUsingSubqueriesAndByNameUsingWhereClauseAsync(
+ ISession session,
+ int orderNumber,
+ string customerName, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ try
+ {
+ var detachedCriteria =
+ DetachedCriteria
+ .For()
+ .CreateAlias("Orders", "order", JoinType.LeftOuterJoin, Restrictions.Eq("Number", orderNumber))
+ .SetProjection(Projections.Id());
+
+ return
+ session
+ .CreateCriteria()
+ .CreateAlias("Orders", "order1", JoinType.LeftOuterJoin)
+ .Add(Subqueries.PropertyIn("Id", detachedCriteria))
+ .Add(Restrictions.Eq("Name", customerName))
+ .SetResultTransformer(new DistinctRootEntityResultTransformer())
+ .ListAsync(cancellationToken);
+ }
+ catch (System.Exception ex)
+ {
+ return Task.FromException>(ex);
+ }
+ }
+
+ protected override Task> GetAllCustomersAsync(ISession session, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ try
+ {
+ return session.CreateCriteria().ListAsync(cancellationToken);
+ }
+ catch (System.Exception ex)
+ {
+ return Task.FromException>(ex);
+ }
+ }
+ }
+}
diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH3848/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH3848/Fixture.cs
new file mode 100644
index 00000000000..be5a8125f28
--- /dev/null
+++ b/src/NHibernate.Test/Async/NHSpecificTest/NH3848/Fixture.cs
@@ -0,0 +1,620 @@
+//------------------------------------------------------------------------------
+//
+// 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;
+using System.Collections.Generic;
+using System.Data;
+using System.Linq;
+using System.Linq.Expressions;
+using NHibernate.Cache;
+using NHibernate.Cfg;
+using NHibernate.Cfg.MappingSchema;
+using NHibernate.Mapping.ByCode;
+using NUnit.Framework;
+
+namespace NHibernate.Test.NHSpecificTest.NH3848
+{
+ using System.Threading.Tasks;
+ using System.Threading;
+ [TestFixture]
+ public abstract class FixtureAsync : TestCaseMappingByCode
+ {
+ protected Customer Customer1;
+ protected Customer Customer2;
+ protected Customer Customer3;
+ protected const int OrderNumber = 2;
+
+ protected override HbmMapping GetMappings()
+ {
+ var mapper = new ModelMapper();
+ mapper.Class(rc =>
+ {
+ rc.Table("Customers");
+ rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
+ rc.Property(x => x.Name);
+ rc.Set(x => x.Orders, m =>
+ {
+ m.Inverse(true);
+ m.Key(k =>
+ {
+ k.Column("CustomerId");
+ k.NotNullable(true);
+ });
+ m.Cascade(Mapping.ByCode.Cascade.All.Include(Mapping.ByCode.Cascade.DeleteOrphans));
+ m.Cache(c => c.Usage(CacheUsage.ReadWrite));
+ }, m => m.OneToMany());
+
+ rc.Set(x => x.Companies, m =>
+ {
+ m.Inverse(true);
+ m.Key(k =>
+ {
+ k.Column("CustomerId");
+ k.NotNullable(true);
+ });
+ m.Cascade(Mapping.ByCode.Cascade.All.Include(Mapping.ByCode.Cascade.DeleteOrphans));
+ m.Cache(c => c.Usage(CacheUsage.ReadWrite));
+ }, m => m.OneToMany());
+ });
+
+ mapper.Class(rc =>
+ {
+ rc.Table("Orders");
+ rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
+ rc.Property(x => x.Number, m => m.Column("`Number`"));
+ rc.ManyToOne(x => x.Customer, m => m.Column("CustomerId"));
+ rc.Cache(c => c.Usage(CacheUsage.ReadWrite));
+ });
+
+ mapper.Class(rc =>
+ {
+ rc.Table("Companies");
+ rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
+ rc.Property(x => x.Name);
+ rc.ManyToOne(x => x.Customer, m => m.Column("CustomerId"));
+ rc.Cache(c => c.Usage(CacheUsage.ReadWrite));
+ });
+
+ return mapper.CompileMappingForAllExplicitlyAddedEntities();
+ }
+
+ protected override void Configure(Configuration configuration)
+ {
+ base.Configure(configuration);
+ configuration.Cache(c =>
+ {
+ c.UseQueryCache = true;
+ c.Provider();
+ });
+ }
+
+ protected override void OnSetUp()
+ {
+ using (var session = OpenSession())
+ using (var transaction = session.BeginTransaction())
+ {
+ Customer1 = new Customer { Name = "First Customer" };
+
+ Customer2 = new Customer { Name = "Second Customer" };
+
+ Customer3 = new Customer { Name = "Third Customer" };
+
+ var customer1Order1 = new Order { Number = 1 };
+ var customer1Company1 = new Company { Name = "First" };
+ Customer1.AddOrder(customer1Order1);
+ Customer1.AddCompany(customer1Company1);
+
+ var customer1Order2 = new Order { Number = 2 };
+ var customer1Company2 = new Company { Name = "Second" };
+ Customer1.AddOrder(customer1Order2);
+ Customer1.AddCompany(customer1Company2);
+
+ var customer2Order1 = new Order { Number = 1 };
+ var customer2Company1 = new Company { Name = "First" };
+ Customer2.AddOrder(customer2Order1);
+ Customer2.AddCompany(customer2Company1);
+
+ var customer2Order2 = new Order { Number = 2 };
+ var customer2Company2 = new Company { Name = "Second" };
+ Customer2.AddOrder(customer2Order2);
+ Customer2.AddCompany(customer2Company2);
+
+ var customer3Company1 = new Company { Name = "First" };
+ var customer3Order1 = new Order { Number = 1 };
+ Customer3.AddOrder(customer3Order1);
+ Customer3.AddCompany(customer3Company1);
+
+ session.Save(Customer1);
+ session.Save(Customer2);
+ session.Save(Customer3);
+
+ transaction.Commit();
+ session.Flush();
+ }
+ }
+
+ protected override void OnTearDown()
+ {
+ ClearSecondLevelCacheFor(typeof(Customer));
+ ClearCollectionCache(n => n.Orders);
+ ClearCollectionCache(n => n.Companies);
+ ClearSecondLevelCacheFor(typeof(Order));
+
+ using (var session = OpenSession())
+ using (var transaction = session.BeginTransaction())
+ {
+ session.Delete("from System.Object");
+
+ session.Flush();
+ transaction.Commit();
+ }
+ }
+
+ [Test]
+ public virtual async Task ChildCollectionsFromLeftOuterJoinWithOnClauseRestrictionOnCollectionShouldNotBeInSecondLevelCacheAsync()
+ {
+ var firstSession = OpenSession();
+ var customersWithOrderNumberEqualsTo2 = await (GetCustomersByOrderNumberUsingOnClauseAsync(firstSession, OrderNumber));
+
+ var secondSession = OpenSession();
+ var customers = await (GetAllCustomersAsync(secondSession));
+
+ Assert.That(
+ customersWithOrderNumberEqualsTo2.Single(n => n.Id == Customer1.Id).Orders,
+ Has.Count.EqualTo(Customer1.Orders.Count(n => n.Number == OrderNumber)));
+ Assert.That(
+ customersWithOrderNumberEqualsTo2.Single(n => n.Id == Customer2.Id).Orders,
+ Has.Count.EqualTo(Customer2.Orders.Count(n => n.Number == OrderNumber)));
+ Assert.That(
+ customersWithOrderNumberEqualsTo2.Single(n => n.Id == Customer3.Id).Orders,
+ Has.Count.EqualTo(Customer3.Orders.Count(n => n.Number == OrderNumber)));
+
+ Assert.That(customers.Single(n => n.Id == Customer1.Id).Orders, Has.Count.EqualTo(Customer1.Orders.Count));
+ Assert.That(customers.Single(n => n.Id == Customer2.Id).Orders, Has.Count.EqualTo(Customer2.Orders.Count));
+ Assert.That(customers.Single(n => n.Id == Customer3.Id).Orders, Has.Count.EqualTo(Customer3.Orders.Count));
+
+ firstSession.Dispose();
+ secondSession.Dispose();
+ }
+
+ [Test]
+ public virtual async Task ChildCollectionsWithSelectModeFetchOnCollectionShouldNotBeInSecondLevelCacheAsync()
+ {
+ var firstSession = OpenSession();
+ var customersWithOrderNumberEqualsTo2 = await (GetCustomersByOrderNumberUsingFetchAsync(firstSession, OrderNumber));
+
+ var secondSession = OpenSession();
+ var customers = await (GetAllCustomersAsync(secondSession));
+
+ Assert.That(
+ customersWithOrderNumberEqualsTo2.Single(n => n.Id == Customer1.Id).Orders,
+ Has.Count.EqualTo(Customer1.Orders.Count(n => n.Number == OrderNumber)));
+ Assert.That(
+ customersWithOrderNumberEqualsTo2.Single(n => n.Id == Customer2.Id).Orders,
+ Has.Count.EqualTo(Customer2.Orders.Count(n => n.Number == OrderNumber)));
+ Assert.That(
+ customersWithOrderNumberEqualsTo2,
+ Has.Count.EqualTo(2));
+
+ Assert.That(customers.Single(n => n.Id == Customer1.Id).Orders, Has.Count.EqualTo(Customer1.Orders.Count));
+ Assert.That(customers.Single(n => n.Id == Customer2.Id).Orders, Has.Count.EqualTo(Customer2.Orders.Count));
+ Assert.That(customers.Single(n => n.Id == Customer3.Id).Orders, Has.Count.EqualTo(Customer3.Orders.Count));
+
+ firstSession.Dispose();
+ secondSession.Dispose();
+ }
+
+ [Test]
+ public virtual async Task ChildCollectionsWithSelectModeFetchAndWhereClauseShouldNotBeInSecondLevelCacheAsync()
+ {
+ var firstSession = OpenSession();
+ var customersWithOrderNumberEqualsTo2 = await (GetCustomersByOrderNumberUsingFetchAndWhereClauseAsync(firstSession, OrderNumber));
+
+ var secondSession = OpenSession();
+ var customers = await (GetAllCustomersAsync(secondSession));
+
+ Assert.That(
+ customersWithOrderNumberEqualsTo2.Single(n => n.Id == Customer1.Id).Orders,
+ Has.Count.EqualTo(Customer1.Orders.Count(n => n.Number == OrderNumber)));
+ Assert.That(
+ customersWithOrderNumberEqualsTo2.Single(n => n.Id == Customer2.Id).Orders,
+ Has.Count.EqualTo(Customer2.Orders.Count(n => n.Number == OrderNumber)));
+ Assert.That(
+ customersWithOrderNumberEqualsTo2,
+ Has.Count.EqualTo(2));
+
+ Assert.That(customers.Single(n => n.Id == Customer1.Id).Orders, Has.Count.EqualTo(Customer1.Orders.Count));
+ Assert.That(customers.Single(n => n.Id == Customer2.Id).Orders, Has.Count.EqualTo(Customer2.Orders.Count));
+ Assert.That(customers.Single(n => n.Id == Customer3.Id).Orders, Has.Count.EqualTo(Customer3.Orders.Count));
+
+ firstSession.Dispose();
+ secondSession.Dispose();
+ }
+
+
+ [Test]
+ public async Task ChildCollectionsFromLeftOuterJoinWithWhereClauseRestrictionOnCollectionShouldNotBeInSecondLevelCacheAsync()
+ {
+ var firstSession = OpenSession();
+ var customersWithOrderNumberEqualsTo2 = await (GetCustomersByOrderNumberUsingWhereClauseAsync(firstSession, OrderNumber));
+
+ var secondSession = OpenSession();
+ var customers = await (GetAllCustomersAsync(secondSession));
+
+ Assert.That(
+ customersWithOrderNumberEqualsTo2.Single(n => n.Id == Customer1.Id).Orders,
+ Has.Count.EqualTo(Customer1.Orders.Count(n => n.Number == OrderNumber)));
+ Assert.That(
+ customersWithOrderNumberEqualsTo2.Single(n => n.Id == Customer2.Id).Orders,
+ Has.Count.EqualTo(Customer2.Orders.Count(n => n.Number == OrderNumber)));
+
+ Assert.That(customers.Single(n => n.Id == Customer3.Id).Orders, Has.Count.EqualTo(Customer3.Orders.Count));
+ Assert.That(customers.Single(n => n.Id == Customer1.Id).Orders, Has.Count.EqualTo(Customer1.Orders.Count));
+ Assert.That(customers.Single(n => n.Id == Customer2.Id).Orders, Has.Count.EqualTo(Customer2.Orders.Count));
+
+ firstSession.Dispose();
+ secondSession.Dispose();
+ }
+
+ [Test]
+ public async Task ChildCollectionsEagerFetchedShouldBeInSecondLevelCacheAsync()
+ {
+ var firstSession = OpenSession();
+ var customersWithOrderNumberEqualsTo2 = await (GetCustomersWithOrdersEagerLoadedAsync(firstSession));
+
+ using (var session = OpenSession())
+ using (IDbCommand cmd = session.Connection.CreateCommand())
+ {
+ cmd.CommandText = "DELETE FROM Orders";
+ cmd.ExecuteNonQuery();
+ cmd.Connection.Close();
+ }
+
+ var secondSession = OpenSession();
+ var customers = await (GetAllCustomersAsync(secondSession));
+
+ Assert.That(
+ customersWithOrderNumberEqualsTo2.Single(n => n.Id == Customer1.Id).Orders,
+ Has.Count.EqualTo(Customer1.Orders.Count));
+ Assert.That(
+ customersWithOrderNumberEqualsTo2.Single(n => n.Id == Customer2.Id).Orders,
+ Has.Count.EqualTo(Customer2.Orders.Count));
+
+ Assert.That(customers.Single(n => n.Id == Customer3.Id).Orders, Has.Count.EqualTo(Customer3.Orders.Count));
+ Assert.That(customers.Single(n => n.Id == Customer1.Id).Orders, Has.Count.EqualTo(Customer1.Orders.Count));
+ Assert.That(customers.Single(n => n.Id == Customer2.Id).Orders, Has.Count.EqualTo(Customer2.Orders.Count));
+
+ firstSession.Dispose();
+ secondSession.Dispose();
+ }
+
+ [Test]
+ public async Task ChildCollectionsFromLeftOuterJoinWithWhereClauseRestrictionOnRootShouldBeInSecondLevelCacheAsync()
+ {
+ var firstSession = OpenSession();
+ var customersWithOrderNumberEqualsTo2 = await (GetCustomersByNameUsingWhereClauseAsync(firstSession, "First Customer"));
+
+ using (var session = OpenSession())
+ using (IDbCommand cmd = session.Connection.CreateCommand())
+ {
+ cmd.CommandText = "DELETE FROM Orders";
+ cmd.ExecuteNonQuery();
+ cmd.Connection.Close();
+ }
+
+ var secondSession = OpenSession();
+ var customers = await (secondSession.GetAsync(Customer1.Id));
+
+ Assert.That(
+ customersWithOrderNumberEqualsTo2.Single(n => n.Id == Customer1.Id).Orders,
+ Has.Count.EqualTo(Customer1.Orders.Count));
+ Assert.That(customers.Orders, Has.Count.EqualTo(Customer1.Orders.Count));
+
+ firstSession.Dispose();
+ secondSession.Dispose();
+ }
+
+ [Test]
+ public async Task ChildCollectionsFromLeftOuterJoinShouldBeInSecondLevelCacheIfQueryContainsSubqueryWithRestrictionOnLeftOuterJoinAsync()
+ {
+ var firstSession = OpenSession();
+ var customersWithOrderNumberEqualsTo2 =
+ await (GetCustomersByOrderNumberUsingSubqueriesAndByNameUsingWhereClauseAsync(
+ firstSession,
+ OrderNumber,
+ Customer1.Name));
+
+ var secondSession = OpenSession();
+ var customers = await (GetAllCustomersAsync(secondSession));
+
+ Assert.That(
+ customersWithOrderNumberEqualsTo2.Single(n => n.Id == Customer1.Id).Orders,
+ Has.Count.EqualTo(Customer1.Orders.Count));
+
+ using (var thirdSession = OpenSession())
+ using (IDbCommand cmd = thirdSession.Connection.CreateCommand())
+ {
+ cmd.CommandText = "DELETE FROM Orders";
+ cmd.ExecuteNonQuery();
+ cmd.Connection.Close();
+ }
+
+ Assert.That(customers.Single(n => n.Id == Customer1.Id).Orders, Has.Count.EqualTo(Customer1.Orders.Count));
+ Assert.That(customers.Single(n => n.Id == Customer2.Id).Orders, Has.Count.EqualTo(0));
+ Assert.That(customers.Single(n => n.Id == Customer3.Id).Orders, Has.Count.EqualTo(0));
+
+ firstSession.Dispose();
+ secondSession.Dispose();
+ }
+
+ [Test]
+ public virtual async Task ChildCollectionsFromLeftOuterJoinOnlyWithRestrictionShouldNotBeIn2LvlCacheAsync()
+ {
+ var firstSession = OpenSession();
+ var customersWithOrderNumberEqualsTo2AndCompanies =
+ await (GetCustomersWithCompaniesByOrderNumberUsingOnClauseAsync(firstSession, OrderNumber));
+
+ using (var session = OpenSession())
+ using (IDbCommand cmd = session.Connection.CreateCommand())
+ {
+ cmd.CommandText = "DELETE FROM Orders";
+ cmd.ExecuteNonQuery();
+ cmd.Connection.Close();
+ }
+
+ using (var session = OpenSession())
+ using (IDbCommand cmd = session.Connection.CreateCommand())
+ {
+ cmd.CommandText = "DELETE FROM Companies";
+ cmd.ExecuteNonQuery();
+ cmd.Connection.Close();
+ }
+
+ var secondSession = OpenSession();
+ var customers = await (GetAllCustomersAsync(secondSession));
+
+ Assert.That(
+ customersWithOrderNumberEqualsTo2AndCompanies.First(n => n.Id == Customer1.Id).Orders,
+ Has.Count.EqualTo(Customer1.Orders.Count(n => n.Number == OrderNumber)));
+ Assert.That(
+ customersWithOrderNumberEqualsTo2AndCompanies.First(n => n.Id == Customer2.Id).Orders,
+ Has.Count.EqualTo(Customer2.Orders.Count(n => n.Number == OrderNumber)));
+ Assert.That(
+ customersWithOrderNumberEqualsTo2AndCompanies.First(n => n.Id == Customer3.Id).Orders,
+ Has.Count.EqualTo(Customer3.Orders.Count(n => n.Number == OrderNumber)));
+
+ Assert.That(
+ customersWithOrderNumberEqualsTo2AndCompanies.First(n => n.Id == Customer1.Id).Companies,
+ Has.Count.EqualTo(Customer1.Companies.Count));
+ Assert.That(
+ customersWithOrderNumberEqualsTo2AndCompanies.First(n => n.Id == Customer2.Id).Companies,
+ Has.Count.EqualTo(Customer2.Companies.Count));
+ Assert.That(
+ customersWithOrderNumberEqualsTo2AndCompanies.First(n => n.Id == Customer3.Id).Companies,
+ Has.Count.EqualTo(Customer3.Companies.Count));
+
+ Assert.That(customers.Single(n => n.Id == Customer1.Id).Orders, Has.Count.EqualTo(0));
+ Assert.That(customers.Single(n => n.Id == Customer2.Id).Orders, Has.Count.EqualTo(0));
+ Assert.That(customers.Single(n => n.Id == Customer3.Id).Orders, Has.Count.EqualTo(0));
+
+ Assert.That(
+ customers.Single(n => n.Id == Customer1.Id).Companies,
+ Has.Count.EqualTo(Customer1.Companies.Count));
+ Assert.That(
+ customers.Single(n => n.Id == Customer2.Id).Companies,
+ Has.Count.EqualTo(Customer2.Companies.Count));
+ Assert.That(
+ customers.Single(n => n.Id == Customer3.Id).Companies,
+ Has.Count.EqualTo(Customer3.Companies.Count));
+
+ firstSession.Dispose();
+ secondSession.Dispose();
+ }
+
+ [Test]
+ public virtual async Task ChildCollectionsWithoutRestrictionShouldBeIn2LvlCacheAsync()
+ {
+ var firstSession = OpenSession();
+ var customersWithOrdersAndCompaniesWithoutRestrictions =
+ await (GetCustomersAndCompaniesByOrderNumberUsingFetchWithoutRestrictionsAsync(firstSession));
+
+ using (var session = OpenSession())
+ using (IDbCommand cmd = session.Connection.CreateCommand())
+ {
+ cmd.CommandText = "DELETE FROM Orders";
+ cmd.ExecuteNonQuery();
+ cmd.Connection.Close();
+ }
+
+ using (var session = OpenSession())
+ using (IDbCommand cmd = session.Connection.CreateCommand())
+ {
+ cmd.CommandText = "DELETE FROM Companies";
+ cmd.ExecuteNonQuery();
+ cmd.Connection.Close();
+ }
+
+ var secondSession = OpenSession();
+ var customers = await (GetAllCustomersAsync(secondSession));
+
+ Assert.That(
+ customersWithOrdersAndCompaniesWithoutRestrictions.First(n => n.Id == Customer1.Id).Orders,
+ Has.Count.EqualTo(Customer1.Orders.Count()));
+ Assert.That(
+ customersWithOrdersAndCompaniesWithoutRestrictions.First(n => n.Id == Customer2.Id).Orders,
+ Has.Count.EqualTo(Customer2.Orders.Count()));
+ Assert.That(
+ customersWithOrdersAndCompaniesWithoutRestrictions.First(n => n.Id == Customer3.Id).Orders,
+ Has.Count.EqualTo(Customer3.Orders.Count()));
+
+ Assert.That(
+ customersWithOrdersAndCompaniesWithoutRestrictions.First(n => n.Id == Customer1.Id).Companies,
+ Has.Count.EqualTo(Customer1.Companies.Count));
+ Assert.That(
+ customersWithOrdersAndCompaniesWithoutRestrictions.First(n => n.Id == Customer2.Id).Companies,
+ Has.Count.EqualTo(Customer2.Companies.Count));
+ Assert.That(
+ customersWithOrdersAndCompaniesWithoutRestrictions.First(n => n.Id == Customer3.Id).Companies,
+ Has.Count.EqualTo(Customer3.Companies.Count));
+
+ Assert.That(
+ customers.First(n => n.Id == Customer1.Id).Orders,
+ Has.Count.EqualTo(Customer1.Orders.Count()));
+ Assert.That(
+ customers.First(n => n.Id == Customer2.Id).Orders,
+ Has.Count.EqualTo(Customer2.Orders.Count()));
+ Assert.That(
+ customers.First(n => n.Id == Customer3.Id).Orders,
+ Has.Count.EqualTo(Customer3.Orders.Count()));
+
+ Assert.That(
+ customers.First(n => n.Id == Customer1.Id).Companies,
+ Has.Count.EqualTo(Customer1.Companies.Count()));
+ Assert.That(
+ customers.First(n => n.Id == Customer2.Id).Companies,
+ Has.Count.EqualTo(Customer2.Companies.Count()));
+ Assert.That(
+ customers.First(n => n.Id == Customer3.Id).Companies,
+ Has.Count.EqualTo(Customer3.Companies.Count()));
+
+ firstSession.Dispose();
+ secondSession.Dispose();
+ }
+
+ [Test]
+ public virtual async Task ChildCollectionsWithRestrictionShouldNotBeIn2LvlCacheAsync()
+ {
+ var firstSession = OpenSession();
+ var customersWithOrdersAndCompaniesWithRestrictions =
+ await (GetCustomersAndCompaniesByOrderNumberUsingFetchAndWhereClauseAsync(firstSession, OrderNumber, "Second"));
+
+ using (var session = OpenSession())
+ using (IDbCommand cmd = session.Connection.CreateCommand())
+ {
+ cmd.CommandText = "DELETE FROM Orders";
+ cmd.ExecuteNonQuery();
+ cmd.Connection.Close();
+ }
+
+ using (var session = OpenSession())
+ using (IDbCommand cmd = session.Connection.CreateCommand())
+ {
+ cmd.CommandText = "DELETE FROM Companies";
+ cmd.ExecuteNonQuery();
+ cmd.Connection.Close();
+ }
+
+ var secondSession = OpenSession();
+ var customers = await (GetAllCustomersAsync(secondSession));
+
+ Assert.That(
+ customersWithOrdersAndCompaniesWithRestrictions.First(n => n.Id == Customer1.Id).Orders,
+ Has.Count.EqualTo(Customer1.Orders.Count(n => n.Number == OrderNumber)));
+ Assert.That(
+ customersWithOrdersAndCompaniesWithRestrictions.First(n => n.Id == Customer2.Id).Orders,
+ Has.Count.EqualTo(Customer2.Orders.Count(n => n.Number == OrderNumber)));
+
+ Assert.That(
+ customersWithOrdersAndCompaniesWithRestrictions.First(n => n.Id == Customer1.Id).Companies,
+ Has.Count.EqualTo(Customer1.Companies.Count(n => n.Name == "Second")));
+ Assert.That(
+ customersWithOrdersAndCompaniesWithRestrictions.First(n => n.Id == Customer2.Id).Companies,
+ Has.Count.EqualTo(Customer2.Companies.Count(n => n.Name == "Second")));
+
+ Assert.That(customers.Single(n => n.Id == Customer1.Id).Orders, Has.Count.EqualTo(0));
+ Assert.That(customers.Single(n => n.Id == Customer2.Id).Orders, Has.Count.EqualTo(0));
+ Assert.That(customers.Single(n => n.Id == Customer3.Id).Orders, Has.Count.EqualTo(0));
+
+ Assert.That(
+ customers.Single(n => n.Id == Customer1.Id).Companies,
+ Has.Count.EqualTo(0));
+ Assert.That(
+ customers.Single(n => n.Id == Customer2.Id).Companies,
+ Has.Count.EqualTo(0));
+ Assert.That(
+ customers.Single(n => n.Id == Customer3.Id).Companies,
+ Has.Count.EqualTo(0));
+
+ firstSession.Dispose();
+ secondSession.Dispose();
+ }
+
+ protected async Task ClearSecondLevelCacheForAsync(System.Type entity, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var entityName = entity.FullName;
+ await (Sfi.EvictEntityAsync(entityName, cancellationToken));
+ var entityPersister = Sfi.GetEntityPersister(entityName);
+ if (!entityPersister.HasCache)
+ return;
+
+ var querySpaces = entityPersister.QuerySpaces.ToList().AsReadOnly();
+ await (Sfi.UpdateTimestampsCache.PreInvalidateAsync(querySpaces, cancellationToken));
+ }
+
+ protected void ClearSecondLevelCacheFor(System.Type entity)
+ {
+ var entityName = entity.FullName;
+ Sfi.EvictEntity(entityName);
+ var entityPersister = Sfi.GetEntityPersister(entityName);
+ if (!entityPersister.HasCache)
+ return;
+
+ var querySpaces = entityPersister.QuerySpaces.ToList().AsReadOnly();
+ Sfi.UpdateTimestampsCache.PreInvalidate(querySpaces);
+ }
+
+ protected Task ClearCollectionCacheAsync(Expression> pathToCollection, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ try
+ {
+ var rootEntityTypeFullPath = typeof(T).FullName;
+ var memberExpression = pathToCollection.Body as MemberExpression;
+ if (memberExpression == null)
+ return Task.FromException