diff --git a/doc/reference/modules/performance.xml b/doc/reference/modules/performance.xml
index 2a1aa29a721..1cd041b08af 100644
--- a/doc/reference/modules/performance.xml
+++ b/doc/reference/modules/performance.xml
@@ -1216,131 +1216,194 @@ sessionFactory.EvictCollection("Eg.Cat.Kittens");]]>
- Multi Query
-
+ Query batch
+
- This functionality allows you to execute several HQL queries in one round-trip
+ This functionality allows you to execute several queries in one round-trip
against the database server. A simple use case is executing a paged query while
- also getting the total count of results, in a single round-trip. Here is a simple
+ also getting the total count of results, in a single round-trip. Here is an
example:
+
+ (
+ s.CreateQuery("from Item i where i.Id > ?")
+ .SetInt32(0, 50).SetFirstResult(10))
+ .Add(
+ s.CreateQuery("select count(*) from Item i where i.Id > :id")
+ .SetInt32("id", 50));
+IList items = queries.GetResult(0);
+long count = queries.GetResult(1).Single();]]>
+
+
+ The results are got by index, ordered according to the order of queries
+ added to the query batch. Instead of relying on this ordering, a key can be
+ associated with each query for later retrieval:
+
+
+ ().Where(i => i.Id > 50))
+ .Add("count", s.Query().Where(i => i.Id > 50), q => q.Count());
+var count = queries.GetResult("count").Single();
+var items = queries.GetResult("list");]]>
+
+
+ The namespace NHibernate.Multi has to be imported since most query
+ batch methods are extension methods.
+
+
+
+ Criteria queries are also supported by the query batch:
+
- ?")
- .SetInt32(0, 50).SetFirstResult(10))
- .Add(s.CreateQuery("select count(*) from Item i where i.Id > ?")
- .SetInt32(0, 50));
-IList results = multiQuery.List();
-IList items = (IList)results[0];
-long count = (long)((IList)results[1])[0];]]>
+ (
+ s.CreateCriteria(typeof(Item))
+ .Add(Expression.Gt("Id", 50))
+ .SetFirstResult(10))
+ .Add(
+ s.CreateCriteria(typeof(Item))
+ .Add(Expression.Gt("Id", 50))
+ .SetProject(Projections.RowCount()));
+var items = queries.GetResult(0);
+var count = queries.GetResult(1).Single();]]>
- The result is a list of query results, ordered according to the order of queries
- added to the multi query. Named parameters can be set on the multi query, and are
- shared among all the queries contained in the multi query, like this:
+ You can add ICriteria or DetachedCriteria to the query batch.
+ In fact, using DetachedCriteria in this fashion has some interesting implications.
+ (customersCriteria)
+ .Add(DetachedCriteria.For()
+ .Add(Subqueries.PropertyIn("id",
+ CriteriaTransformer.Clone(customersCriteria)
+ .SetProjection(Projections.Id())
+ )));
- :id")
- .SetFirstResult(10))
- .Add("select count(*) from Item i where i.Id > :id")
- .SetInt32("id", 50)
- .List();
-IList items = (IList)results[0];
-long count = (long)((IList)results[1])[0];]]>
+IList customers = queries.GetResult(0);
+IList policies = queries.GetResult(1);]]>
- Positional parameters are not supported on the multi query, only on the individual
- queries.
+ We get a query that represents the customers we can access, and then we can utilize this
+ query further in order to perform additional logic (getting the policies of the customers we are
+ associated with), all in a single database round-trip.
- As shown above, if you do not need to configure the query separately, you can simply
- pass the HQL directly to the IMultiQuery.Add() method.
+ The query batch also supports QueryOver and sql queries. All kind of queries can be mixed in the
+ same batch.
+ ().Where(i => i.Category == "Food"))
+ .Add("sqlCount",
+ s.CreateSQLQuery("select count(*) as itemCount from Item i where i.Category = :cat")
+ .AddScalar("itemCount", NHibernateUtil.Int64)
+ .SetString("cat", "Food"));
+var count = queries.GetResult("sqlCount").Single();
+var items = queries.GetResult("queryOverList");]]>
+
+
+ Second level cache is supported by the query batch. Queries flagged as cacheable will be retrieved
+ from the cache if already cached, otherwise their results will be put in the cache.
+
+
+ ()
+ .Where(i => i.Id > 50)
+ .WithOptions(o => o.SetCacheable(true)))
+ .Add("count",
+ s.CreateQuery("select count(*) from Item i where i.Id > :id")
+ .SetInt32("id", 50)
+ .SetCacheable(true));
+var count = queries.GetResult("count").Single();
+var items = queries.GetResult("list");]]>
+
Multi query is executed by concatenating the queries and sending the query to the database
as a single string. This means that the database should support returning several result sets
- in a single query. At the moment this functionality is only enabled for Microsoft SQL Server and SQLite.
+ in a single query. Otherwise each query will be individually executed instead.
+
+
+
+ The first GetResult call triggers execution of the whole query batch, which
+ then stores all results. Later calls only retrieve the stored results. A query batch can be
+ re-executed by calling its Execute method. Once executed, no new query can be
+ added to the batch.
- Note that the database server is likely to impose a limit on the maximum number of parameters
- in a query, in which case the limit applies to the multi query as a whole. Queries using
+ Note that the database server is likely to enforce a limit on the maximum number of parameters
+ in a query, in which case the limit applies to the query batch as a whole. Queries using
in with a large number of arguments passed as parameters may easily exceed
this limit. For example, SQL Server has a limit of 2,100 parameters per round-trip, and will
throw an exception executing this query:
-
-
+
+ (
+ s.CreateQuery("from Employee e where e.Id in :empIds")
+ .SetParameterList("empIds", allEmployeesId)
+ .SetFirstResult(10))
+ .Add(
+ s.CreateQuery("select count(*) from Employee e where e.Id in :empIds")
+ .SetParameterList("empIds", allEmployeesId));
+queries.Execute(); // will throw an exception from SQL Server]]>
- An interesting usage of this feature is to load several collections of an object in one
+ An interesting usage of the query batch is to load several collections of an object in one
round-trip, without an expensive cartesian product (blog * users * posts).
- ();]]>
+ (0).FirstOrDefault();]]>
-
-
-
- Multi Criteria
-
- This is the counter-part to Multi Query, and allows you to perform several criteria queries
- in a single round trip. A simple use case is executing a paged query while
- also getting the total count of results, in a single round-trip. Here is a simple
- example:
+ You can also add queries as future queries to a query batch:
-
-
-
- The result is a list of query results, ordered according to the order of queries
- added to the multi criteria.
-
+
- You can add ICriteria or DetachedCriteria to the Multi Criteria query.
- In fact, using DetachedCriteria in this fashion has some interesting implications.
-
- ()
- .Add(Subqueries.PropertyIn("id",
- CriteriaTransformer.Clone(customersCriteria)
- .SetProjection(Projections.Id())
- )))
- .List();
+...
-ICollection customers = CollectionHelper.ToArray(results[0]);
-ICollection policies = CollectionHelper.ToArray(results[1]);]]>
+var queries = s.CreateQueryBatch();
+var list = queries.AddAsFuture(s.Query().Where(i => i.Id > 50)));
+var countValue = queries.AddAsFutureValue(
+ s.CreateQuery("select count(*) from Item i where i.Id > :id")
+ .SetInt32("id", 50));
+var count = countValue.Value;
+var items = list.GetEnumerable();]]>
- As you see, we get a query that represents the customers we can access, and then we can utilize this query further in order to
- perform additional logic (getting the policies of the customers we are associated with), all in a single database round-trip.
+ Futures built from a query batch are executed together the first time the result of one of
+ them is accessed. They are independent of futures obtained directly from the queries.
+
diff --git a/src/NHibernate.Test/Async/Criteria/Lambda/IntegrationFixture.cs b/src/NHibernate.Test/Async/Criteria/Lambda/IntegrationFixture.cs
index 06b04fc0deb..017634dc4f5 100644
--- a/src/NHibernate.Test/Async/Criteria/Lambda/IntegrationFixture.cs
+++ b/src/NHibernate.Test/Async/Criteria/Lambda/IntegrationFixture.cs
@@ -16,6 +16,7 @@
using NUnit.Framework;
using NHibernate.Criterion;
+using NHibernate.Multi;
namespace NHibernate.Test.Criteria.Lambda
{
@@ -352,7 +353,7 @@ public async Task FunctionsOrderAsync()
}
}
- [Test]
+ [Test, Obsolete]
public async Task MultiCriteriaAsync()
{
var driver = Sfi.ConnectionProvider.Driver;
@@ -408,6 +409,58 @@ public async Task MultiCriteriaAsync()
}
}
+ [Test]
+ public async Task MultiQueryAsync()
+ {
+ await (SetupPagingDataAsync());
+
+ using (var s = OpenSession())
+ {
+ var query =
+ s.QueryOver()
+ .JoinQueryOver(p => p.Children)
+ .OrderBy(c => c.Age).Desc
+ .Skip(2)
+ .Take(1);
+
+ var multiQuery =
+ s.CreateQueryBatch()
+ .Add("page", query)
+ .Add("count", query.ToRowCountQuery());
+
+ var pageResults = await (multiQuery.GetResultAsync("page", CancellationToken.None));
+ var countResults = await (multiQuery.GetResultAsync("count", CancellationToken.None));
+
+ Assert.That(pageResults.Count, Is.EqualTo(1));
+ Assert.That(pageResults[0].Name, Is.EqualTo("Name 3"));
+ Assert.That(countResults.Count, Is.EqualTo(1));
+ Assert.That(countResults[0], Is.EqualTo(4));
+ }
+
+ using (var s = OpenSession())
+ {
+ var query =
+ QueryOver.Of()
+ .JoinQueryOver(p => p.Children)
+ .OrderBy(c => c.Age).Desc
+ .Skip(2)
+ .Take(1);
+
+ var multiCriteria =
+ s.CreateQueryBatch()
+ .Add("page", query)
+ .Add("count", query.ToRowCountQuery());
+
+ var pageResults = await (multiCriteria.GetResultAsync("page", CancellationToken.None));
+ var countResults = await (multiCriteria.GetResultAsync("count", CancellationToken.None));
+
+ Assert.That(pageResults.Count, Is.EqualTo(1));
+ Assert.That(pageResults[0].Name, Is.EqualTo("Name 3"));
+ Assert.That(countResults.Count, Is.EqualTo(1));
+ Assert.That(countResults[0], Is.EqualTo(4));
+ }
+ }
+
private async Task SetupPagingDataAsync(CancellationToken cancellationToken = default(CancellationToken))
{
using (ISession s = OpenSession())
diff --git a/src/NHibernate.Test/Async/NHSpecificTest/DataReaderWrapperTest/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/DataReaderWrapperTest/Fixture.cs
index 0ef21cbc6f9..6178bdea7c2 100644
--- a/src/NHibernate.Test/Async/NHSpecificTest/DataReaderWrapperTest/Fixture.cs
+++ b/src/NHibernate.Test/Async/NHSpecificTest/DataReaderWrapperTest/Fixture.cs
@@ -8,17 +8,20 @@
//------------------------------------------------------------------------------
+using System;
using System.Collections;
using NUnit.Framework;
+using NHibernate.Multi;
namespace NHibernate.Test.NHSpecificTest.DataReaderWrapperTest
{
using System.Threading.Tasks;
+ using System.Threading;
[TestFixture]
public class FixtureAsync : BugTestCase
{
private const int id = 1333;
-
+
protected override bool AppliesTo(Engine.ISessionFactoryImplementor factory)
{
return factory.ConnectionProvider.Driver.SupportsMultipleQueries;
@@ -45,7 +48,7 @@ protected override void OnTearDown()
}
}
- [Test]
+ [Test, Obsolete]
public async Task CanUseDatareadersGetValueAsync()
{
using (var s = OpenSession())
@@ -58,5 +61,19 @@ public async Task CanUseDatareadersGetValueAsync()
Assert.That(res.Count, Is.EqualTo(1));
}
}
+
+ [Test]
+ public async Task CanUseDatareadersGetValueWithQueryBatchAsync()
+ {
+ using (var s = OpenSession())
+ using (s.BeginTransaction())
+ {
+ var crit = s.CreateCriteria(typeof (TheEntity));
+ var multi = s.CreateQueryBatch();
+ multi.Add(crit);
+ var res = await (multi.GetResultAsync(0, CancellationToken.None));
+ Assert.That(res.Count, Is.EqualTo(1));
+ }
+ }
}
}
diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH1253/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH1253/Fixture.cs
index 0dbec500db2..9919113e183 100644
--- a/src/NHibernate.Test/Async/NHSpecificTest/NH1253/Fixture.cs
+++ b/src/NHibernate.Test/Async/NHSpecificTest/NH1253/Fixture.cs
@@ -8,14 +8,14 @@
//------------------------------------------------------------------------------
-using System.Collections;
-using System.Collections.Generic;
-using NHibernate.Driver;
+using System;
using NUnit.Framework;
+using NHibernate.Multi;
namespace NHibernate.Test.NHSpecificTest.NH1253
{
using System.Threading.Tasks;
+ using System.Threading;
[TestFixture]
public class FixtureAsync : BugTestCase
{
@@ -81,7 +81,7 @@ public async Task TestParametersWithTrailingNumbersMultipleInListAsync()
}
}
- [Test]
+ [Test, Obsolete]
public async Task MultiQuerySingleInListAsync()
{
var driver = Sfi.ConnectionProvider.Driver;
@@ -101,5 +101,28 @@ public async Task MultiQuerySingleInListAsync()
await (tx.CommitAsync());
}
}
+
+ [Test]
+ public async Task QueryBatchSingleInListAsync()
+ {
+ using (var s = OpenSession())
+ using (var tx = s.BeginTransaction())
+ {
+ var q1 = s
+ .CreateQuery("from Car c where c.Make in (:param1) or c.Model in (:param11)")
+ .SetParameterList("param11", new[] {"Model1", "Model2"})
+ .SetParameterList("param1", new[] {"Make1", "Make2"});
+ var q2 = s
+ .CreateQuery("from Car c where c.Make in (:param1) or c.Model in (:param11)")
+ .SetParameterList("param11", new[] {"Model1", "Model2"})
+ .SetParameterList("param1", new[] {"Make1", "Make2"});
+ await (s.CreateQueryBatch()
+ .Add(q1)
+ .Add(q2)
+ .ExecuteAsync(CancellationToken.None));
+
+ await (tx.CommitAsync());
+ }
+ }
}
}
diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH1508/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH1508/Fixture.cs
index 920db7f3fae..bd1b7cb21a5 100644
--- a/src/NHibernate.Test/Async/NHSpecificTest/NH1508/Fixture.cs
+++ b/src/NHibernate.Test/Async/NHSpecificTest/NH1508/Fixture.cs
@@ -8,11 +8,14 @@
//------------------------------------------------------------------------------
+using System;
using NUnit.Framework;
+using NHibernate.Multi;
namespace NHibernate.Test.NHSpecificTest.NH1508
{
using System.Threading.Tasks;
+ using System.Threading;
[TestFixture]
public class FixtureAsync : BugTestCase
{
@@ -54,7 +57,7 @@ protected override void OnTearDown()
}
}
- [Test]
+ [Test, Obsolete]
public async Task DoesntThrowExceptionWhenHqlQueryIsGivenAsync()
{
using (var session = OpenSession())
@@ -67,5 +70,19 @@ public async Task DoesntThrowExceptionWhenHqlQueryIsGivenAsync()
await (q.ListAsync());
}
}
+
+ [Test]
+ public async Task DoesntThrowExceptionWhenHqlQueryIsGivenToQueryBatchAsync()
+ {
+ using (var session = OpenSession())
+ using (session.BeginTransaction())
+ {
+ var sqlQuery = session.CreateQuery("from Document");
+ var q = session
+ .CreateQueryBatch()
+ .Add(sqlQuery);
+ await (q.ExecuteAsync(CancellationToken.None));
+ }
+ }
}
}
diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH1609/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH1609/Fixture.cs
index f64a4444dbd..0ef9c665113 100644
--- a/src/NHibernate.Test/Async/NHSpecificTest/NH1609/Fixture.cs
+++ b/src/NHibernate.Test/Async/NHSpecificTest/NH1609/Fixture.cs
@@ -8,9 +8,10 @@
//------------------------------------------------------------------------------
+using System;
using System.Collections;
using NHibernate.Criterion;
-using NHibernate.Driver;
+using NHibernate.Multi;
using NUnit.Framework;
namespace NHibernate.Test.NHSpecificTest.NH1609
@@ -25,7 +26,7 @@ protected override bool AppliesTo(Engine.ISessionFactoryImplementor factory)
return factory.ConnectionProvider.Driver.SupportsMultipleQueries;
}
- [Test]
+ [Test, Obsolete]
public async Task TestAsync()
{
using (var session = Sfi.OpenSession())
@@ -59,6 +60,38 @@ public async Task TestAsync()
}
}
+ [Test]
+ public async Task TestWithQueryBatchAsync()
+ {
+ using (var session = Sfi.OpenSession())
+ using (session.BeginTransaction())
+ {
+ var a1 = await (CreateEntityAAsync(session));
+ var a2 = await (CreateEntityAAsync(session));
+ var c = await (CreateEntityCAsync(session));
+ var b = await (CreateEntityBAsync(session, a1, c));
+
+ // make sure the created entities are no longer in the session
+ session.Clear();
+
+ var multi = session.CreateQueryBatch();
+
+ // the first query is a simple select by id on EntityA
+ multi.Add(session.CreateCriteria(typeof (EntityA)).Add(Restrictions.Eq("Id", a1.Id)));
+ // the second query is also a simple select by id on EntityB
+ multi.Add(session.CreateCriteria(typeof (EntityA)).Add(Restrictions.Eq("Id", a2.Id)));
+ // the final query selects the first element (using SetFirstResult and SetMaxResults) for each EntityB where B.A.Id = a1.Id and B.C.Id = c.Id
+ // the problem is that the paged query uses parameters @p0 and @p1 instead of @p2 and @p3
+ multi.Add(
+ session.CreateCriteria(typeof (EntityB)).Add(Restrictions.Eq("A.Id", a1.Id)).Add(Restrictions.Eq("C.Id", c.Id)).
+ SetFirstResult(0).SetMaxResults(1));
+
+ Assert.That(await (multi.GetResultAsync(0, CancellationToken.None)), Has.Count.EqualTo(1));
+ Assert.That(await (multi.GetResultAsync(1, CancellationToken.None)), Has.Count.EqualTo(1));
+ Assert.That(await (multi.GetResultAsync(2, CancellationToken.None)), Has.Count.EqualTo(1));
+ }
+ }
+
private async Task CreateEntityAAsync(ISession session, CancellationToken cancellationToken = default(CancellationToken))
{
var a = new EntityA();
diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH1836/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH1836/Fixture.cs
index 5380c9ee98b..5bd5c737d32 100644
--- a/src/NHibernate.Test/Async/NHSpecificTest/NH1836/Fixture.cs
+++ b/src/NHibernate.Test/Async/NHSpecificTest/NH1836/Fixture.cs
@@ -8,13 +8,17 @@
//------------------------------------------------------------------------------
+using System;
using System.Collections;
+using System.Linq;
+using NHibernate.Multi;
using NHibernate.Transform;
using NUnit.Framework;
namespace NHibernate.Test.NHSpecificTest.NH1836
{
using System.Threading.Tasks;
+ using System.Threading;
[TestFixture]
public class FixtureAsync : BugTestCase
{
@@ -35,7 +39,7 @@ protected override void OnSetUp()
}
}
- [Test]
+ [Test, Obsolete]
public void AliasToBeanTransformerShouldApplyCorrectlyToMultiQueryAsync()
{
using (var s = OpenSession())
@@ -53,6 +57,25 @@ public void AliasToBeanTransformerShouldApplyCorrectlyToMultiQueryAsync()
}
}
+ [Test]
+ public async Task AliasToBeanTransformerShouldApplyCorrectlyToQueryBatchAsync()
+ {
+ using (var s = OpenSession())
+ using (var t = s.BeginTransaction())
+ {
+ var multiQuery = s
+ .CreateQueryBatch()
+ .Add(s
+ .CreateQuery("select entity.Id as EntityId from Entity entity")
+ .SetResultTransformer(Transformers.AliasToBean(typeof(EntityDTO))));
+
+ Assert.That(multiQuery.Execute, Throws.Nothing);
+ var results = await (multiQuery.GetResultAsync(0, CancellationToken.None));
+ Assert.That(results.First(), Is.TypeOf().And.Property("EntityId").EqualTo(1));
+ await (t.CommitAsync());
+ }
+ }
+
protected override void OnTearDown()
{
base.OnTearDown();
diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH1869/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH1869/Fixture.cs
index 0137e1fcc94..99e5824c791 100644
--- a/src/NHibernate.Test/Async/NHSpecificTest/NH1869/Fixture.cs
+++ b/src/NHibernate.Test/Async/NHSpecificTest/NH1869/Fixture.cs
@@ -8,8 +8,9 @@
//------------------------------------------------------------------------------
+using System;
using System.Collections;
-using NHibernate.Driver;
+using NHibernate.Multi;
using NUnit.Framework;
namespace NHibernate.Test.NHSpecificTest.NH1869
@@ -38,7 +39,7 @@ protected override void OnTearDown()
}
}
- [Test]
+ [Test, Obsolete]
public async Task TestAsync()
{
using (var session = Sfi.OpenSession())
@@ -57,7 +58,7 @@ public async Task TestAsync()
using (var session = Sfi.OpenSession())
{
- //If uncomment the line below the test will pass
+ //If querying twice the test will pass
//GetResult(session);
var result = await (GetResultAsync(session));
Assert.That(result, Has.Count.EqualTo(2));
@@ -66,6 +67,7 @@ public async Task TestAsync()
}
}
+ [Obsolete]
private Task GetResultAsync(ISession session, CancellationToken cancellationToken = default(CancellationToken))
{
try
@@ -77,10 +79,48 @@ public async Task TestAsync()
multi.Add(query1).Add(query2);
return multi.ListAsync(cancellationToken);
}
- catch (System.Exception ex)
+ catch (Exception ex)
{
return Task.FromException(ex);
}
}
+
+ [Test]
+ public async Task TestWithQueryBatchAsync()
+ {
+ using (var session = Sfi.OpenSession())
+ using (var transaction = session.BeginTransaction())
+ {
+ _keyword = new Keyword();
+ await (session.SaveAsync(_keyword));
+
+ var nodeKeyword = new NodeKeyword
+ {
+ NodeId = 1,
+ Keyword = _keyword
+ };
+ await (session.SaveAsync(nodeKeyword));
+
+ await (transaction.CommitAsync());
+ }
+
+ using (var session = Sfi.OpenSession())
+ {
+ var result = await (GetResultWithQueryBatchAsync(session));
+ Assert.That(await (result.GetResultAsync(0, CancellationToken.None)), Has.Count.EqualTo(1));
+ Assert.That(await (result.GetResultAsync(1, CancellationToken.None)), Has.Count.EqualTo(1));
+ }
+ }
+
+ private async Task GetResultWithQueryBatchAsync(ISession session, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var query1 = session.CreateQuery("from NodeKeyword nk");
+ var query2 = session.CreateQuery("from NodeKeyword nk");
+
+ var multi = session.CreateQueryBatch();
+ multi.Add(query1).Add(query2);
+ await (multi.ExecuteAsync(cancellationToken));
+ return multi;
+ }
}
}
diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH2195/SQLiteMultiCriteriaTest.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH2195/SQLiteMultiCriteriaTest.cs
index 332bf71a088..549d14f3d6f 100644
--- a/src/NHibernate.Test/Async/NHSpecificTest/NH2195/SQLiteMultiCriteriaTest.cs
+++ b/src/NHibernate.Test/Async/NHSpecificTest/NH2195/SQLiteMultiCriteriaTest.cs
@@ -11,15 +11,16 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using System.Text;
+using System.Linq;
using NHibernate.Criterion;
using NHibernate.Dialect;
-using NHibernate.Tool.hbm2ddl;
+using NHibernate.Multi;
using NUnit.Framework;
namespace NHibernate.Test.NHSpecificTest.NH2195
{
using System.Threading.Tasks;
+ using System.Threading;
[TestFixture]
public class SQLiteMultiCriteriaTestAsync : BugTestCase
{
@@ -97,7 +98,7 @@ public async Task SingleCriteriaQueriesWithStringsShouldExecuteCorrectlyAsync()
}
}
- [Test]
+ [Test, Obsolete]
public async Task MultiCriteriaQueriesWithIntsShouldExecuteCorrectlyAsync()
{
var driver = Sfi.ConnectionProvider.Driver;
@@ -126,7 +127,7 @@ public async Task MultiCriteriaQueriesWithIntsShouldExecuteCorrectlyAsync()
}
}
- [Test]
+ [Test, Obsolete]
public async Task MultiCriteriaQueriesWithStringsShouldExecuteCorrectlyAsync()
{
var driver = Sfi.ConnectionProvider.Driver;
@@ -155,5 +156,55 @@ public async Task MultiCriteriaQueriesWithStringsShouldExecuteCorrectlyAsync()
Assert.AreEqual(1, list.Count);
}
}
+
+ [Test]
+ public async Task QueryBatchWithIntsShouldExecuteCorrectlyAsync()
+ {
+ // Test querying IntData
+ using (var session = OpenSession())
+ {
+ var criteriaWithPagination = session.CreateCriteria();
+ criteriaWithPagination.Add(Restrictions.Le("IntData", 2));
+ var criteriaWithRowCount = CriteriaTransformer.Clone(criteriaWithPagination);
+ criteriaWithPagination.SetFirstResult(0).SetMaxResults(1);
+ criteriaWithRowCount.SetProjection(Projections.RowCountInt64());
+
+ var multi = session.CreateQueryBatch();
+ multi.Add(criteriaWithPagination);
+ multi.Add(criteriaWithRowCount);
+
+ var numResults = (await (multi.GetResultAsync(1, CancellationToken.None))).Single();
+ var list = await (multi.GetResultAsync(0, CancellationToken.None));
+
+ Assert.That(numResults, Is.EqualTo(2));
+ Assert.That(list.Count, Is.EqualTo(1));
+ Assert.That(await (criteriaWithRowCount.UniqueResultAsync()), Is.EqualTo(2));
+ }
+ }
+
+ [Test]
+ public async Task QueryBatchWithStringsShouldExecuteCorrectlyAsync()
+ {
+ // Test querying StringData
+ using (var session = OpenSession())
+ {
+ var criteriaWithPagination = session.CreateCriteria();
+ criteriaWithPagination.Add(Restrictions.Like("StringData", "%Doe%"));
+ var criteriaWithRowCount = CriteriaTransformer.Clone(criteriaWithPagination);
+ criteriaWithPagination.SetFirstResult(0).SetMaxResults(1);
+ criteriaWithRowCount.SetProjection(Projections.RowCountInt64());
+
+ var multi = session.CreateQueryBatch();
+ multi.Add(criteriaWithPagination);
+ multi.Add(criteriaWithRowCount);
+
+ var numResults = (await (multi.GetResultAsync(1, CancellationToken.None))).Single();
+ var list = await (multi.GetResultAsync(0, CancellationToken.None));
+
+ Assert.That(numResults, Is.EqualTo(2));
+ Assert.That(list.Count, Is.EqualTo(1));
+ Assert.That(await (criteriaWithRowCount.UniqueResultAsync()), Is.EqualTo(2));
+ }
+ }
}
}
diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH2201/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH2201/Fixture.cs
index 793f910f486..c8d31458508 100644
--- a/src/NHibernate.Test/Async/NHSpecificTest/NH2201/Fixture.cs
+++ b/src/NHibernate.Test/Async/NHSpecificTest/NH2201/Fixture.cs
@@ -10,11 +10,13 @@
using System;
using System.Collections.Generic;
+using NHibernate.Multi;
using NUnit.Framework;
namespace NHibernate.Test.NHSpecificTest.NH2201
{
using System.Threading.Tasks;
+ using System.Threading;
[TestFixture]
public class FixtureAsync : BugTestCase
{
@@ -45,7 +47,7 @@ protected override void OnSetUp()
}
}
- [Test]
+ [Test, Obsolete]
public async Task CanUseMutliCriteriaAndFetchSelectAsync()
{
using (var s = OpenSession())
@@ -65,5 +67,23 @@ public async Task CanUseMutliCriteriaAndFetchSelectAsync()
Console.WriteLine("*** end");
}
}
+
+ [Test]
+ public async Task CanUseQueryBatchAndFetchSelectAsync()
+ {
+ using (var s = OpenSession())
+ {
+ var multi =
+ s.CreateQueryBatch()
+ .Add(s.CreateCriteria())
+ .Add(s.CreateCriteria());
+
+ var result1 = await (multi.GetResultAsync(0, CancellationToken.None));
+ var result2 = await (multi.GetResultAsync(1, CancellationToken.None));
+
+ Assert.That(result1.Count, Is.EqualTo(2));
+ Assert.That(result2.Count, Is.EqualTo(2));
+ }
+ }
}
}
diff --git a/src/NHibernate.Test/Async/NHSpecificTest/NH2959/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/NH2959/Fixture.cs
index 463b6bd0447..68829391305 100644
--- a/src/NHibernate.Test/Async/NHSpecificTest/NH2959/Fixture.cs
+++ b/src/NHibernate.Test/Async/NHSpecificTest/NH2959/Fixture.cs
@@ -8,11 +8,14 @@
//------------------------------------------------------------------------------
+using System;
+using NHibernate.Multi;
using NUnit.Framework;
namespace NHibernate.Test.NHSpecificTest.NH2959
{
using System.Threading.Tasks;
+ using System.Threading;
[TestFixture]
public class FixtureAsync : BugTestCase
{
@@ -48,7 +51,7 @@ protected override void OnTearDown()
}
}
- [Test]
+ [Test, Obsolete]
public async Task CanUsePolymorphicCriteriaInMultiCriteriaAsync()
{
using (ISession session = OpenSession())
@@ -63,7 +66,7 @@ public async Task CanUsePolymorphicCriteriaInMultiCriteriaAsync()
}
}
- [Test]
+ [Test, Obsolete]
public async Task CanUsePolymorphicQueryInMultiQueryAsync()
{
using (ISession session = OpenSession())
@@ -77,5 +80,33 @@ public async Task CanUsePolymorphicQueryInMultiQueryAsync()
Assert.That(results[0], Has.Count.EqualTo(2));
}
}
+
+ [Test]
+ public async Task CanUsePolymorphicCriteriaInQueryBatchAsync()
+ {
+ using (var session = OpenSession())
+ using (session.BeginTransaction())
+ {
+ var results = await (session.CreateQueryBatch()
+ .Add(session.CreateCriteria(typeof(BaseEntity)))
+ .GetResultAsync(0, CancellationToken.None));
+
+ Assert.That(results, Has.Count.EqualTo(2));
+ }
+ }
+
+ [Test]
+ public async Task CanUsePolymorphicQueryInQueryBatchAsync()
+ {
+ using (var session = OpenSession())
+ using (session.BeginTransaction())
+ {
+ var results = await (session.CreateQueryBatch()
+ .Add(session.CreateQuery("from " + typeof(BaseEntity).FullName))
+ .GetResultAsync(0, CancellationToken.None));
+
+ Assert.That(results, Has.Count.EqualTo(2));
+ }
+ }
}
-}
\ No newline at end of file
+}
diff --git a/src/NHibernate.Test/Async/NHSpecificTest/SqlConverterAndMultiQuery/Fixture.cs b/src/NHibernate.Test/Async/NHSpecificTest/SqlConverterAndMultiQuery/Fixture.cs
index fc8c339848e..0875183d026 100644
--- a/src/NHibernate.Test/Async/NHSpecificTest/SqlConverterAndMultiQuery/Fixture.cs
+++ b/src/NHibernate.Test/Async/NHSpecificTest/SqlConverterAndMultiQuery/Fixture.cs
@@ -8,14 +8,17 @@
//------------------------------------------------------------------------------
+using System;
using NHibernate.Cfg;
using NHibernate.Driver;
using NHibernate.Engine;
+using NHibernate.Multi;
using NUnit.Framework;
namespace NHibernate.Test.NHSpecificTest.SqlConverterAndMultiQuery
{
using System.Threading.Tasks;
+ using System.Threading;
[TestFixture]
public class FixtureAsync : BugTestCase
{
@@ -47,7 +50,7 @@ public void NormalHqlShouldThrowUserExceptionAsync()
}
}
- [Test]
+ [Test, Obsolete]
public void MultiHqlShouldThrowUserExceptionAsync()
{
var driver = Sfi.ConnectionProvider.Driver;
@@ -64,6 +67,19 @@ public void MultiHqlShouldThrowUserExceptionAsync()
}
}
+ [Test]
+ public void QueryBatchShouldThrowUserExceptionAsync()
+ {
+ using (var s = OpenSession())
+ using (s.BeginTransaction())
+ {
+ var multi = s.CreateQueryBatch();
+ multi.Add(s.CreateQuery(hqlQuery));
+ s.Connection.Close();
+ Assert.ThrowsAsync(() => multi.ExecuteAsync(CancellationToken.None));
+ }
+ }
+
[Test]
public void NormalCriteriaShouldThrowUserExceptionAsync()
{
@@ -76,7 +92,7 @@ public void NormalCriteriaShouldThrowUserExceptionAsync()
}
}
- [Test]
+ [Test, Obsolete]
public void MultiCriteriaShouldThrowUserExceptionAsync()
{
var driver = Sfi.ConnectionProvider.Driver;
@@ -92,5 +108,18 @@ public void MultiCriteriaShouldThrowUserExceptionAsync()
Assert.ThrowsAsync(() => multi.ListAsync());
}
}
+
+ [Test]
+ public void CriteriaQueryBatchShouldThrowUserExceptionAsync()
+ {
+ using (var s = OpenSession())
+ using (s.BeginTransaction())
+ {
+ var multi = s.CreateQueryBatch();
+ multi.Add(s.CreateCriteria(typeof(ClassA)));
+ s.Connection.Close();
+ Assert.ThrowsAsync(() => multi.ExecuteAsync(CancellationToken.None));
+ }
+ }
}
}
diff --git a/src/NHibernate.Test/Async/Pagination/CustomDialectFixture.cs b/src/NHibernate.Test/Async/Pagination/CustomDialectFixture.cs
index b252f0c06b9..6a0526e1272 100644
--- a/src/NHibernate.Test/Async/Pagination/CustomDialectFixture.cs
+++ b/src/NHibernate.Test/Async/Pagination/CustomDialectFixture.cs
@@ -8,12 +8,14 @@
//------------------------------------------------------------------------------
+using System;
using System.Collections;
using System.Collections.Generic;
using NHibernate.Cfg;
using NHibernate.Criterion;
using NHibernate.Dialect;
using NHibernate.Driver;
+using NHibernate.Multi;
using NHibernate.Util;
using NUnit.Framework;
using Environment = NHibernate.Cfg.Environment;
@@ -21,6 +23,7 @@
namespace NHibernate.Test.Pagination
{
using System.Threading.Tasks;
+ using System.Threading;
[TestFixture]
public class CustomDialectFixtureAsync : TestCase
{
@@ -109,7 +112,7 @@ public async Task LimitFirstAsync()
}
}
- [Test]
+ [Test, Obsolete]
public async Task LimitFirstMultiCriteriaAsync()
{
using (ISession s = OpenSession())
@@ -133,5 +136,30 @@ public async Task LimitFirstMultiCriteriaAsync()
Assert.That(points[1].X, Is.EqualTo(8d));
}
}
+
+ [Test]
+ public async Task LimitFirstQueryBatchAsync()
+ {
+ using (var s = OpenSession())
+ {
+ CustomDialect.ForcedSupportsVariableLimit = true;
+ CustomDialect.ForcedBindLimitParameterFirst = true;
+
+ var query =
+ s.CreateQueryBatch()
+ .Add(
+ s.CreateCriteria()
+ .Add(Restrictions.Gt("X", 5.1d))
+ .AddOrder(Order.Asc("X"))
+ .SetFirstResult(1)
+ .SetMaxResults(2));
+
+ var points = await (query.GetResultAsync(0, CancellationToken.None));
+
+ Assert.That(points.Count, Is.EqualTo(2));
+ Assert.That(points[0].X, Is.EqualTo(7d));
+ Assert.That(points[1].X, Is.EqualTo(8d));
+ }
+ }
}
-}
\ No newline at end of file
+}
diff --git a/src/NHibernate.Test/Async/QueryTest/MultiCriteriaFixture.cs b/src/NHibernate.Test/Async/QueryTest/MultiCriteriaFixture.cs
index 8e4a638691e..16026d41f87 100644
--- a/src/NHibernate.Test/Async/QueryTest/MultiCriteriaFixture.cs
+++ b/src/NHibernate.Test/Async/QueryTest/MultiCriteriaFixture.cs
@@ -21,7 +21,7 @@ namespace NHibernate.Test.QueryTest
{
using System.Threading.Tasks;
using System.Threading;
- [TestFixture]
+ [TestFixture, Obsolete]
public class MultiCriteriaFixtureAsync : TestCase
{
protected override string MappingsAssembly
diff --git a/src/NHibernate.Test/Async/QueryTest/MultipleMixedQueriesFixture.cs b/src/NHibernate.Test/Async/QueryTest/MultipleMixedQueriesFixture.cs
index 967c15f25ae..5fc7d5f721a 100644
--- a/src/NHibernate.Test/Async/QueryTest/MultipleMixedQueriesFixture.cs
+++ b/src/NHibernate.Test/Async/QueryTest/MultipleMixedQueriesFixture.cs
@@ -11,7 +11,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
-using NHibernate.Driver;
using NHibernate.Test.SecondLevelCacheTests;
using NUnit.Framework;
@@ -19,7 +18,7 @@ namespace NHibernate.Test.QueryTest
{
using System.Threading.Tasks;
using System.Threading;
- [TestFixture]
+ [TestFixture, Obsolete]
public class MultipleMixedQueriesFixtureAsync : TestCase
{
protected override string MappingsAssembly
diff --git a/src/NHibernate.Test/Async/QueryTest/MultipleQueriesFixture.cs b/src/NHibernate.Test/Async/QueryTest/MultipleQueriesFixture.cs
index 7961618cf52..688bce5dc72 100644
--- a/src/NHibernate.Test/Async/QueryTest/MultipleQueriesFixture.cs
+++ b/src/NHibernate.Test/Async/QueryTest/MultipleQueriesFixture.cs
@@ -21,7 +21,7 @@ namespace NHibernate.Test.QueryTest
{
using System.Threading.Tasks;
using System.Threading;
- [TestFixture]
+ [TestFixture, Obsolete]
public class MultipleQueriesFixtureAsync : TestCase
{
protected override string MappingsAssembly
@@ -474,4 +474,4 @@ public async Task CanGetResultsInAGenericListClassAsync()
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/NHibernate.Test/Async/QueryTest/QueryBatchFixture.cs b/src/NHibernate.Test/Async/QueryTest/QueryBatchFixture.cs
new file mode 100644
index 00000000000..6f42383623c
--- /dev/null
+++ b/src/NHibernate.Test/Async/QueryTest/QueryBatchFixture.cs
@@ -0,0 +1,938 @@
+//------------------------------------------------------------------------------
+//
+// 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 System.Linq;
+using NHibernate.Cfg;
+using NHibernate.Criterion;
+using NHibernate.Multi;
+using NHibernate.Test.SecondLevelCacheTests;
+using NUnit.Framework;
+using Environment = NHibernate.Cfg.Environment;
+
+namespace NHibernate.Test.QueryTest
+{
+ using System.Threading.Tasks;
+ using System.Threading;
+ [TestFixture]
+ public class QueryBatchFixtureAsync : TestCase
+ {
+ // This fixture aggregates most of the tests from MultiCriteriaFixture, MultipleMixedQueriesFixture and
+ // MultipleQueriesFixture, rewritten for using QueryBatch instead of obsoleted MultiCriteria/MultiQuery.
+
+ protected override string MappingsAssembly => "NHibernate.Test";
+
+ protected override string[] Mappings => new[] { "SecondLevelCacheTest.Item.hbm.xml" };
+
+ protected override void Configure(Configuration configuration)
+ {
+ configuration.SetProperty(Environment.GenerateStatistics, "true");
+ }
+
+ protected override void OnSetUp()
+ {
+ Sfi.Statistics.Clear();
+ }
+
+ protected override void OnTearDown()
+ {
+ using (var session = OpenSession())
+ using (var transaction = session.BeginTransaction())
+ {
+ session.Delete("from System.Object");
+ session.Flush();
+ transaction.Commit();
+ }
+ }
+
+ #region Criteria
+
+ [Test]
+ public async Task CanExecuteMultipleCriteriaQueriesInSingleRoundTrip_InTransactionAsync()
+ {
+ using (var s = OpenSession())
+ {
+ var item = new Item
+ {
+ Id = 1,
+ Name = "foo"
+ };
+ await (s.SaveAsync(item));
+ await (s.FlushAsync());
+ }
+
+ using (var s = OpenSession())
+ using (var transaction = s.BeginTransaction())
+ {
+ var getItems = s.CreateCriteria(typeof(Item));
+ var countItems = s.CreateCriteria(typeof(Item))
+ .SetProjection(Projections.RowCount());
+
+ var queries = s.CreateQueryBatch()
+ .Add(getItems)
+ .Add(countItems);
+ var items = await (queries.GetResultAsync(0, CancellationToken.None));
+ var fromDb = items.First();
+ Assert.That(fromDb.Id, Is.EqualTo(1));
+ Assert.That(fromDb.Name, Is.EqualTo("foo"));
+
+ var count = (await (queries.GetResultAsync(1, CancellationToken.None))).Single();
+ Assert.That(count, Is.EqualTo(1));
+
+ await (transaction.CommitAsync());
+ }
+ }
+
+ [Test]
+ public async Task CanExecuteMultipleCriteriaQueriesInSingleRoundTripAsync()
+ {
+ using (var s = OpenSession())
+ {
+ var item = new Item { Id = 1 };
+ await (s.SaveAsync(item));
+ await (s.FlushAsync());
+ }
+
+ using (var s = OpenSession())
+ {
+ var getItems = s.CreateCriteria(typeof(Item));
+ var countItems = s.CreateCriteria(typeof(Item))
+ .SetProjection(Projections.RowCount());
+
+ var queries = s.CreateQueryBatch()
+ .Add(getItems)
+ .Add(countItems);
+ var items = await (queries.GetResultAsync(0, CancellationToken.None));
+ var fromDb = items.First();
+ Assert.That(fromDb.Id, Is.EqualTo(1));
+
+ var count = (await (queries.GetResultAsync(1, CancellationToken.None))).Single();
+ Assert.That(count, Is.EqualTo(1));
+ }
+ }
+
+ [Test]
+ public async Task CanUseSecondLevelCacheWithPositionalParametersAndCriteriaAsync()
+ {
+ await (Sfi.QueryCache.ClearAsync(CancellationToken.None));
+
+ await (CreateItemsAsync());
+
+ Sfi.Statistics.Clear();
+
+ await (DoMultiCriteriaAndAssertAsync());
+
+ Assert.That(Sfi.Statistics.QueryCachePutCount, Is.EqualTo(2));
+ }
+
+ [Test]
+ public async Task CanGetMultiCriteriaFromSecondLevelCacheAsync()
+ {
+ await (CreateItemsAsync());
+ //set the query in the cache
+ await (DoMultiCriteriaAndAssertAsync());
+ Assert.That(Sfi.Statistics.QueryCachePutCount, Is.EqualTo(2), "Cache puts");
+
+ Sfi.Statistics.Clear();
+ await (DoMultiCriteriaAndAssertAsync());
+ Assert.That(Sfi.Statistics.PrepareStatementCount, Is.EqualTo(0), "Prepared statements");
+ Assert.That(Sfi.Statistics.QueryCacheMissCount, Is.EqualTo(0), "Cache misses");
+ Assert.That(Sfi.Statistics.QueryCacheHitCount, Is.EqualTo(2), "Cache hits");
+ }
+
+ [Test]
+ public async Task CanUpdateStatisticsWhenGetMultiCriteriaFromSecondLevelCacheAsync()
+ {
+ await (CreateItemsAsync());
+
+ await (DoMultiCriteriaAndAssertAsync());
+ Assert.That(Sfi.Statistics.QueryCacheHitCount, Is.EqualTo(0));
+ Assert.That(Sfi.Statistics.QueryCacheMissCount, Is.EqualTo(2));
+ Assert.That(Sfi.Statistics.QueryCachePutCount, Is.EqualTo(2));
+
+ await (DoMultiCriteriaAndAssertAsync());
+ Assert.That(Sfi.Statistics.QueryCacheHitCount, Is.EqualTo(2));
+ Assert.That(Sfi.Statistics.QueryCacheMissCount, Is.EqualTo(2));
+ Assert.That(Sfi.Statistics.QueryCachePutCount, Is.EqualTo(2));
+ }
+
+ [Test]
+ public async Task TwoMultiCriteriaWithDifferentPagingGetDifferentResultsWhenUsingCachedQueriesAsync()
+ {
+ await (CreateItemsAsync());
+ using (var s = OpenSession())
+ {
+ var criteria = s.CreateCriteria(typeof(Item))
+ .Add(Restrictions.Gt("id", 50));
+ var queries = s.CreateQueryBatch()
+ .Add(CriteriaTransformer.Clone(criteria).SetFirstResult(10).SetCacheable(true))
+ .Add(
+ CriteriaTransformer
+ .Clone(criteria).SetProjection(Projections.RowCount()).SetCacheable(true));
+ var items = await (queries.GetResultAsync(0, CancellationToken.None));
+ Assert.That(items.Count, Is.EqualTo(89));
+ var count = (await (queries.GetResultAsync(1, CancellationToken.None))).Single();
+ Assert.That(count, Is.EqualTo(99));
+ }
+
+ using (var s = OpenSession())
+ {
+ var criteria = s.CreateCriteria(typeof(Item))
+ .Add(Restrictions.Gt("id", 50));
+ var queries = s.CreateQueryBatch()
+ .Add(CriteriaTransformer.Clone(criteria).SetFirstResult(20).SetCacheable(true))
+ .Add(
+ CriteriaTransformer
+ .Clone(criteria).SetProjection(Projections.RowCount()).SetCacheable(true));
+ var items = await (queries.GetResultAsync(0, CancellationToken.None));
+ Assert.That(
+ items.Count,
+ Is.EqualTo(79),
+ "Should have gotten different result here, because the paging is different");
+ var count = (await (queries.GetResultAsync(1, CancellationToken.None))).Single();
+ Assert.That(count, Is.EqualTo(99));
+ }
+ }
+
+ [Test]
+ public async Task CanUseWithParameterizedCriteriaAndLimitAsync()
+ {
+ await (CreateItemsAsync());
+
+ using (var s = OpenSession())
+ {
+ var criteria = s.CreateCriteria(typeof(Item))
+ .Add(Restrictions.Gt("id", 50));
+
+ var queries = s.CreateQueryBatch()
+ .Add(
+ CriteriaTransformer.Clone(criteria)
+ .SetFirstResult(10))
+ .Add(
+ CriteriaTransformer.Clone(criteria)
+ .SetProjection(Projections.RowCount()));
+ var items = await (queries.GetResultAsync(0, CancellationToken.None));
+ Assert.That(items.Count, Is.EqualTo(89));
+ var count = (await (queries.GetResultAsync(1, CancellationToken.None))).Single();
+ Assert.That(count, Is.EqualTo(99));
+ }
+ }
+
+ [Test]
+ public async Task CanUseCriteriaWithParameterListAsync()
+ {
+ using (var s = OpenSession())
+ {
+ var item = new Item { Id = 1 };
+ await (s.SaveAsync(item));
+ await (s.FlushAsync());
+ }
+
+ using (var s = OpenSession())
+ {
+ var criteria = s.CreateCriteria(typeof(Item))
+ .Add(
+ Restrictions.In(
+ "id",
+ new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }));
+ var queries = s.CreateQueryBatch()
+ .Add(CriteriaTransformer.Clone(criteria))
+ .Add(
+ CriteriaTransformer.Clone(criteria)
+ .SetProjection(Projections.RowCount()));
+
+ var items = await (queries.GetResultAsync(0, CancellationToken.None));
+ var fromDb = items.First();
+ Assert.That(fromDb.Id, Is.EqualTo(1));
+
+ var count = (await (queries.GetResultAsync(1, CancellationToken.None))).Single();
+ Assert.That(count, Is.EqualTo(1));
+ }
+ }
+
+ [Test]
+ public async Task CanAddCriteriaWithKeyAndRetrieveResultsWithKeyAsync()
+ {
+ await (CreateItemsAsync());
+
+ using (var session = OpenSession())
+ {
+ var multiCriteria = session.CreateQueryBatch();
+
+ var firstCriteria = session.CreateCriteria(typeof(Item))
+ .Add(Restrictions.Lt("id", 50));
+
+ var secondCriteria = session.CreateCriteria(typeof(Item));
+
+ multiCriteria.Add("firstCriteria", firstCriteria);
+ multiCriteria.Add("secondCriteria", secondCriteria);
+
+ var secondResult = await (multiCriteria.GetResultAsync("secondCriteria", CancellationToken.None));
+ var firstResult = await (multiCriteria.GetResultAsync("firstCriteria", CancellationToken.None));
+
+ Assert.That(secondResult.Count, Is.GreaterThan(firstResult.Count));
+ }
+ }
+
+ [Test]
+ public async Task CanAddDetachedCriteriaWithKeyAndRetrieveResultsWithKeyAsync()
+ {
+ await (CreateItemsAsync());
+
+ using (var session = OpenSession())
+ {
+ var multiCriteria = session.CreateQueryBatch();
+
+ var firstCriteria = DetachedCriteria.For(typeof(Item))
+ .Add(Restrictions.Lt("id", 50));
+
+ var secondCriteria = DetachedCriteria.For(typeof(Item));
+
+ multiCriteria.Add("firstCriteria", firstCriteria);
+ multiCriteria.Add("secondCriteria", secondCriteria);
+
+ var secondResult = await (multiCriteria.GetResultAsync("secondCriteria", CancellationToken.None));
+ var firstResult = await (multiCriteria.GetResultAsync("firstCriteria", CancellationToken.None));
+
+ Assert.That(secondResult.Count, Is.GreaterThan(firstResult.Count));
+ }
+ }
+
+ [Test]
+ public async Task ExecutingCriteriaThroughTransformsResultsAsync()
+ {
+ await (CreateItemsAsync());
+
+ using (var session = OpenSession())
+ {
+ var transformer = new ResultTransformerStub();
+ var criteria = session.CreateCriteria(typeof(Item))
+ .SetResultTransformer(transformer);
+ var multiCriteria = session.CreateQueryBatch()
+ .Add