From 54487083eae0ef495c8438f3c066bd1117f62ec9 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Wed, 23 Dec 2020 17:05:15 +0500 Subject: [PATCH 1/3] Adds async tests for CommandProcessors --- ...ingCommandProcessorParametersManagement.cs | 337 +++++++++++++++++- .../BatchingOfVersionizedEntitiesTest.cs | 47 ++- ...pleCommandProcessorParametersManagement.cs | 183 +++++++++- 3 files changed, 527 insertions(+), 40 deletions(-) diff --git a/Orm/Xtensive.Orm.Tests/Storage/CommandProcessing/BatchingCommandProcessorParametersManagement.cs b/Orm/Xtensive.Orm.Tests/Storage/CommandProcessing/BatchingCommandProcessorParametersManagement.cs index 0f1f4ff90e..59d35b27c3 100644 --- a/Orm/Xtensive.Orm.Tests/Storage/CommandProcessing/BatchingCommandProcessorParametersManagement.cs +++ b/Orm/Xtensive.Orm.Tests/Storage/CommandProcessing/BatchingCommandProcessorParametersManagement.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using NUnit.Framework; using Xtensive.Core; using Xtensive.Orm.Configuration; @@ -28,10 +29,7 @@ protected override DomainConfiguration BuildConfiguration() return config; } - protected override void CheckRequirements() - { - Require.ProviderIs(StorageProvider.SqlServer); - } + protected override void CheckRequirements() => Require.ProviderIs(StorageProvider.SqlServer); protected override void PopulateData() { @@ -55,7 +53,7 @@ public void EachQueryInSeparateCommandTest() using (var session = Domain.OpenSession()) using (var counter = new CommandCounter(session)) using (var transaction = session.OpenTransaction()) { - var ids = Enumerable.Range(1, StorageLimit - 1).ToArray(); + var ids = Enumerable.Range(1, StorageLimit - 1).ToArray(StorageLimit - 1); var results = new List>(10); results.Add(session.Query.ExecuteDelayed(q => @@ -102,13 +100,65 @@ public void EachQueryInSeparateCommandTest() } } + [Test] + public async Task EachQueryInSeparateCommandAsyncTest() + { + using (var session = await Domain.OpenSessionAsync()) + using (var counter = new CommandCounter(session)) + using (var transaction = session.OpenTransaction()) { + var ids = Enumerable.Range(1, StorageLimit - 1).ToArray(StorageLimit - 1); + var results = new List>(10); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + using (counter.Attach()) { + var inlineQuery = await session.Query.All() + .Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)).AsAsync(); + Assert.That(inlineQuery.Any(), Is.True); + Assert.That(counter.Count, Is.EqualTo(11)); + } + + foreach (var result in results) { + Assert.That(result.Any(), Is.True); + } + } + } + [Test] public void InlineQueryInSeparateBatchTest() { using (var session = Domain.OpenSession()) using (var counter = new CommandCounter(session)) using (var transaction = session.OpenTransaction()) { - var ids = Enumerable.Range(1, (StorageLimit - 1) / 2).ToArray(); + var ids = Enumerable.Range(1, (StorageLimit - 1) / 2).ToArray((StorageLimit - 1) / 2); var results = new List>(10); results.Add(session.Query.ExecuteDelayed(q => @@ -155,13 +205,65 @@ public void InlineQueryInSeparateBatchTest() } } + [Test] + public async Task InlineQueryInSeparateBatchAsyncTest() + { + using (var session = await Domain.OpenSessionAsync()) + using (var counter = new CommandCounter(session)) + using (var transaction = session.OpenTransaction()) { + var ids = Enumerable.Range(1, (StorageLimit - 1) / 2).ToArray((StorageLimit - 1) / 2); + var results = new List>(10); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + using (counter.Attach()) { + var inlineQuery = await session.Query.All() + .Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, new[] { 1, 2 })).AsAsync(); + Assert.That(inlineQuery.Any(), Is.True); + Assert.That(counter.Count, Is.EqualTo(6)); + } + + foreach (var result in results) { + Assert.That(result.Any(), Is.True); + } + } + } + [Test] public void InlineQueryInLastBatchTest() { using (var session = Domain.OpenSession()) using (var counter = new CommandCounter(session)) using (var transaction = session.OpenTransaction()) { - var ids = Enumerable.Range(1, (StorageLimit - 3) / 2).ToArray(); + var ids = Enumerable.Range(1, (StorageLimit - 3) / 2).ToArray((StorageLimit - 3) / 2); var results = new List>(10); results.Add(session.Query.ExecuteDelayed(q => @@ -208,14 +310,66 @@ public void InlineQueryInLastBatchTest() } } + [Test] + public async Task InlineQueryInLastBatchAsyncTest() + { + using (var session = await Domain.OpenSessionAsync()) + using (var counter = new CommandCounter(session)) + using (var transaction = session.OpenTransaction()) { + var ids = Enumerable.Range(1, (StorageLimit - 3) / 2).ToArray((StorageLimit - 3) / 2); + var results = new List>(10); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + using (counter.Attach()) { + var inlineQuery = await session.Query.All() + .Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, new[] { 1, 2 })).AsAsync(); + Assert.That(inlineQuery.Any(), Is.True); + Assert.That(counter.Count, Is.EqualTo(5)); + } + + foreach (var result in results) { + Assert.That(result.Any(), Is.True); + } + } + } + [Test] public void DelayedSelectsOutOfLimitTest01() { using (var session = Domain.OpenSession()) using (var counter = new CommandCounter(session)) using (var transaction = session.OpenTransaction()) { - var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(); - var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(); + var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(StorageLimit - 1); + var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(StorageLimit + 1); var result = (DelayedSequence) session.Query.ExecuteDelayed(q => q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, idsOutOfRange))); @@ -228,14 +382,36 @@ public void DelayedSelectsOutOfLimitTest01() } } + [Test] + public async Task DelayedSelectsOutOfLimitAsyncTest01() + { + using (var session = await Domain.OpenSessionAsync()) + using (var counter = new CommandCounter(session)) + using (var transaction = session.OpenTransaction()) { + var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(StorageLimit - 1); + var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(StorageLimit + 1); + + var result = (DelayedSequence) session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, idsOutOfRange))); + + using (counter.Attach()) { + _ = Assert.ThrowsAsync(async () => (await result.AsAsync()).Run()); + } + Assert.That(result.Task.Result.Count, Is.EqualTo(0)); + Assert.That(counter.Count, Is.EqualTo(0)); + var currentSession = Session.Current; + Assert.That(currentSession, Is.EqualTo(session)); + } + } + [Test] public void DelayedSelectsOutOfLimitTest02() { using (var session = Domain.OpenSession()) using (var counter = new CommandCounter(session)) using (var transaction = session.OpenTransaction()) { - var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(); - var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(); + var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(StorageLimit - 1); + var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(StorageLimit + 1); var result = (DelayedSequence) session.Query.ExecuteDelayed(q => q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, idsOutOfRange))); @@ -249,14 +425,36 @@ public void DelayedSelectsOutOfLimitTest02() } } + [Test] + public async Task DelayedSelectsOutOfLimitAsyncTest02() + { + using (var session = await Domain.OpenSessionAsync()) + using (var counter = new CommandCounter(session)) + using (var transaction = session.OpenTransaction()) { + var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(StorageLimit - 1); + var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(StorageLimit + 1); + + var result = (DelayedSequence) session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, idsOutOfRange))); + + using (counter.Attach()) { + _ = Assert.ThrowsAsync( + async () => (await session.Query.All().AsAsync()).Run()); + } + + Assert.That(result.Task.Result.Count, Is.EqualTo(0)); + Assert.That(counter.Count, Is.EqualTo(0)); + } + } + [Test] public void DelayedSelectsOutOfLimitTest03() { using (var session = Domain.OpenSession()) using (var counter = new CommandCounter(session)) using (var transaction = session.OpenTransaction()) { - var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(); - var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(); + var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(StorageLimit - 1); + var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(StorageLimit + 1); var result = (DelayedSequence) session.Query.ExecuteDelayed(q => q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, fittedIds))); @@ -272,7 +470,33 @@ public void DelayedSelectsOutOfLimitTest03() } Assert.That(counter.Count, Is.EqualTo(1)); Assert.That(result.Any(), Is.True); + } + } + + [Test] + public async Task DelayedSelectsOutOfLimitAsyncTest03() + { + using (var session = await Domain.OpenSessionAsync()) + using (var counter = new CommandCounter(session)) + using (var transaction = session.OpenTransaction()) { + var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(StorageLimit - 1); + var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(StorageLimit + 1); + + var result = (DelayedSequence) session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, fittedIds))); + + _ = session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, fittedIds))); + + _ = session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, idsOutOfRange))); + using (counter.Attach()) { + _ = Assert.ThrowsAsync( + async () => (await session.Query.All().AsAsync()).Run()); + } + Assert.That(counter.Count, Is.EqualTo(1)); + Assert.That(result.Any(), Is.True); } } @@ -282,8 +506,31 @@ public void DelayedSelectsOutOfLimitTest04() using (var session = Domain.OpenSession()) using (var counter = new CommandCounter(session)) using (var transaction = session.OpenTransaction()) { - var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(); - var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(); + var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(StorageLimit - 1); + var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(StorageLimit + 1); + + var result = (DelayedSequence) session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, idsOutOfRange))); + + _ = session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, fittedIds))); + + using (counter.Attach()) { + _ = Assert.Throws(() => session.Query.All().Run()); + } + Assert.That(counter.Count, Is.EqualTo(0)); + Assert.That(result.Any(), Is.False); + } + } + + [Test] + public async Task DelayedSelectsOutOfLimitAsyncTest04() + { + using (var session = await Domain.OpenSessionAsync()) + using (var counter = new CommandCounter(session)) + using (var transaction = session.OpenTransaction()) { + var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(StorageLimit - 1); + var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(StorageLimit + 1); var result = (DelayedSequence) session.Query.ExecuteDelayed(q => q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, idsOutOfRange))); @@ -291,7 +538,8 @@ public void DelayedSelectsOutOfLimitTest04() _ = session.Query.ExecuteDelayed(q => q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, fittedIds))); - _ = Assert.Throws(() => session.Query.All().Run()); + _ = Assert.ThrowsAsync( + async () => (await session.Query.All().AsAsync()).Run()); Assert.That(result.Any(), Is.False); } } @@ -302,8 +550,8 @@ public void DelayedSelectsOutOfLimitTest05() using (var session = Domain.OpenSession()) using (var counter = new CommandCounter(session)) using (var transaction = session.OpenTransaction()) { - var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(); - var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(); + var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(StorageLimit - 1); + var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(StorageLimit + 1); var result1 = (DelayedSequence) session.Query.ExecuteDelayed(q => q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, fittedIds))); @@ -322,6 +570,32 @@ public void DelayedSelectsOutOfLimitTest05() } } + [Test] + public async Task DelayedSelectsOutOfLimitAsyncTest05() + { + using (var session = await Domain.OpenSessionAsync()) + using (var counter = new CommandCounter(session)) + using (var transaction = session.OpenTransaction()) { + var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(StorageLimit - 1); + var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(StorageLimit + 1); + + var result1 = (DelayedSequence) session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, fittedIds))); + + var result2 = session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, fittedIds))); + + using (counter.Attach()) { + _ = Assert.ThrowsAsync( + async () => (await session.Query.All() + .Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, idsOutOfRange)).AsAsync()).Run()); + } + Assert.That(counter.Count, Is.EqualTo(1)); + Assert.That(result1.Any(), Is.True); + Assert.That(result2.Any(), Is.False); + } + } + [Test] public void InsertTest01() { @@ -678,5 +952,32 @@ public void PartialExecutionDeniedTest02() Assert.That(counter.Count, Is.EqualTo(2)); } } + + [Test] + public async Task PartialExecutionDeniedAsyncTest02() + { + using (var session = Domain.OpenSession()) + using (var counter = new CommandCounter(session)) + using (var transaction = session.OpenTransaction()) { + var batchSize = session.Configuration.BatchSize; + var currentBatchCapacity = batchSize; + + Console.WriteLine(batchSize); + // one complete batch; + while (currentBatchCapacity > 0) { + _ = new NormalAmountOfFieldsEntity(); + currentBatchCapacity--; + } + + // extra task to have extra batch + _ = new NormalAmountOfFieldsEntity(); + + //persist by query causes allowPartialExecution = true; + using (counter.Attach()) { + (await session.Query.All().AsAsync()).Run(); + } + Assert.That(counter.Count, Is.EqualTo(2)); + } + } } } diff --git a/Orm/Xtensive.Orm.Tests/Storage/CommandProcessing/BatchingOfVersionizedEntitiesTest.cs b/Orm/Xtensive.Orm.Tests/Storage/CommandProcessing/BatchingOfVersionizedEntitiesTest.cs index 2729e2bf96..0560722dfa 100644 --- a/Orm/Xtensive.Orm.Tests/Storage/CommandProcessing/BatchingOfVersionizedEntitiesTest.cs +++ b/Orm/Xtensive.Orm.Tests/Storage/CommandProcessing/BatchingOfVersionizedEntitiesTest.cs @@ -4,6 +4,7 @@ using System; using System.Linq; +using System.Threading.Tasks; using NUnit.Framework; using Xtensive.Core; using Xtensive.Orm.Configuration; @@ -119,10 +120,7 @@ public class BatchingOfVersionizedEntitiesTest : AutoBuildTest private readonly SessionConfiguration sessionWithoutCheck = new SessionConfiguration(SessionOptions.ServerProfile | SessionOptions.AutoActivation); - protected override void CheckRequirements() - { - Require.AllFeaturesSupported(ProviderFeatures.Batches); - } + protected override void CheckRequirements() => Require.AllFeaturesSupported(ProviderFeatures.Batches); protected override DomainConfiguration BuildConfiguration() { @@ -370,6 +368,47 @@ public void VersionedEntityUpdateWithoutVersionCheckTest03() } } + [Test] + public async Task VersionedEntityUpdateWithoutVersionCheckAsyncTest03() + { + using (var session = await Domain.OpenSessionAsync(sessionWithoutCheck)) + using (var counter = new CommandCounter(session)) + using (var transaction = session.OpenTransaction()) { + var store = session.Query.All().Single(el => el.Name == "Store"); + var book = session.Query.All().Single(el => el.Title == "Romeo and Juliet"); + var author = session.Query.All().Single(el => el.FirstName == "William"); + + _ = new Store { Name = "NewStore1" }; + _ = new Store { Name = "NewStore2" }; + book.Title = "AnotherTitle"; + store.Name = "AnotherStore"; + + _ = session.Query.ExecuteDelayed(q => q.All().Take(() => 1)); + _ = session.Query.ExecuteDelayed(q => q.All().Take(() => 2)); + _ = session.Query.ExecuteDelayed(q => q.All().Take(() => 3)); + _ = session.Query.ExecuteDelayed(q => q.All().Take(() => 4)); + + using (counter.Attach()) { + (await session.Query.All().AsAsync()).Run(); + } + + Assert.That(counter.Count, Is.EqualTo(1)); + counter.Reset(); + + _ = new Store { Name = "NewStore3" }; + _ = new Store { Name = "NewStore4" }; + _ = new Store { Name = "NewStore5" }; + + author.FirstName = "NotWilliam"; + + using (counter.Attach()) { + session.SaveChanges(); + } + + Assert.That(counter.Count, Is.EqualTo(1)); + } + } + private bool IsUpdatesFirst() { return !(Domain.Configuration.Supports(ForeignKeyMode.Reference) diff --git a/Orm/Xtensive.Orm.Tests/Storage/CommandProcessing/SimpleCommandProcessorParametersManagement.cs b/Orm/Xtensive.Orm.Tests/Storage/CommandProcessing/SimpleCommandProcessorParametersManagement.cs index 0ed95c45a7..e08a0e63b8 100644 --- a/Orm/Xtensive.Orm.Tests/Storage/CommandProcessing/SimpleCommandProcessorParametersManagement.cs +++ b/Orm/Xtensive.Orm.Tests/Storage/CommandProcessing/SimpleCommandProcessorParametersManagement.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using NUnit.Framework; using Xtensive.Core; using Xtensive.Orm.Configuration; @@ -16,10 +17,7 @@ namespace Xtensive.Orm.Tests.Storage.CommandProcessing { public class SimpleCommandProcessorParametersManagement : AutoBuildTest { - public int StorageLimit - { - get { return ProviderInfo.MaxQueryParameterCount; } - } + public int StorageLimit => ProviderInfo.MaxQueryParameterCount; protected override DomainConfiguration BuildConfiguration() { @@ -29,10 +27,7 @@ protected override DomainConfiguration BuildConfiguration() return config; } - protected override void CheckRequirements() - { - Require.AllFeaturesNotSupported(ProviderFeatures.Batches); - } + protected override void CheckRequirements() => Require.AllFeaturesNotSupported(ProviderFeatures.Batches); protected override void PopulateData() { @@ -94,6 +89,56 @@ public void DelayedSelectsWithinLimitTest() } } + [Test] + public async Task DelayedSelectsWithinLimitAsyncTest() + { + RequireLimit(); + + using (var session = await Domain.OpenSessionAsync()) + using (var transaction = session.OpenTransaction()) { + var ids = Enumerable.Range(1, StorageLimit - 1).ToArray(StorageLimit - 1); + var results = new List>(10); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + results.Add(session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)))); + + var inlineQuery = await session.Query.All() + .Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, ids)).AsAsync(); + Assert.That(inlineQuery.Any(), Is.True); + + foreach (var result in results) { + Assert.That(result.Any(), Is.True); + } + } + } + [Test] public void DelayedSelectsOutOfLimitTest01() { @@ -101,8 +146,8 @@ public void DelayedSelectsOutOfLimitTest01() using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { - var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(); - var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(); + var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(StorageLimit - 1); + var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(StorageLimit + 1); var result = (DelayedSequence) session.Query.ExecuteDelayed(q => q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, idsOutOfRange))); @@ -112,6 +157,24 @@ public void DelayedSelectsOutOfLimitTest01() } } + [Test] + public async Task DelayedSelectsOutOfLimitAsyncTest01() + { + RequireLimit(); + + using (var session = await Domain.OpenSessionAsync()) + using (var transaction = session.OpenTransaction()) { + var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(StorageLimit - 1); + var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(StorageLimit + 1); + + var result = (DelayedSequence) session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, idsOutOfRange))); + + _ = Assert.ThrowsAsync(async () => await result.AsAsync()); + Assert.That(result.Task.Result.Count, Is.EqualTo(0)); + } + } + [Test] public void DelayedSelectsOutOfLimitTest02() { @@ -119,8 +182,8 @@ public void DelayedSelectsOutOfLimitTest02() using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { - var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(); - var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(); + var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(StorageLimit - 1); + var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(StorageLimit + 1); var result = (DelayedSequence) session.Query.ExecuteDelayed(q => q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, idsOutOfRange))); @@ -130,6 +193,24 @@ public void DelayedSelectsOutOfLimitTest02() } } + [Test] + public async Task DelayedSelectsOutOfLimitAsyncTest02() + { + RequireLimit(); + + using (var session = await Domain.OpenSessionAsync()) + using (var transaction = session.OpenTransaction()) { + var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(StorageLimit - 1); + var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(StorageLimit + 1); + + var result = (DelayedSequence) session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, idsOutOfRange))); + + _ = Assert.ThrowsAsync(async () => (await session.Query.All().AsAsync()).Run()); + Assert.That(result.Task.Result.Count, Is.EqualTo(0)); + } + } + [Test] public void DelayedSelectsOutOfLimitTest03() { @@ -137,8 +218,8 @@ public void DelayedSelectsOutOfLimitTest03() using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { - var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(); - var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(); + var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(StorageLimit - 1); + var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(StorageLimit + 1); var result = (DelayedSequence) session.Query.ExecuteDelayed(q => q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, fittedIds))); @@ -151,6 +232,27 @@ public void DelayedSelectsOutOfLimitTest03() } } + [Test] + public async Task DelayedSelectsOutOfLimitAsyncTest03() + { + RequireLimit(); + + using (var session = await Domain.OpenSessionAsync()) + using (var transaction = session.OpenTransaction()) { + var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(StorageLimit - 1); + var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(StorageLimit + 1); + + var result = (DelayedSequence) session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, fittedIds))); + + _ = session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, idsOutOfRange))); + + _ = Assert.ThrowsAsync(async () => (await session.Query.All().AsAsync()).Run()); + Assert.That(result.Any(), Is.True); + } + } + [Test] public void DelayedSelectsOutOfLimitTest04() { @@ -158,8 +260,8 @@ public void DelayedSelectsOutOfLimitTest04() using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { - var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(); - var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(); + var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(StorageLimit - 1); + var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(StorageLimit + 1); var result = (DelayedSequence) session.Query.ExecuteDelayed(q => q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, idsOutOfRange))); @@ -172,6 +274,27 @@ public void DelayedSelectsOutOfLimitTest04() } } + [Test] + public async Task DelayedSelectsOutOfLimitAsyncTest04() + { + RequireLimit(); + + using (var session = await Domain.OpenSessionAsync()) + using (var transaction = session.OpenTransaction()) { + var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(StorageLimit - 1); + var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(StorageLimit + 1); + + var result = (DelayedSequence) session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, idsOutOfRange))); + + _ = session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, fittedIds))); + + _ = Assert.ThrowsAsync(async () => (await session.Query.All().AsAsync()).Run()); + Assert.That(result.Any(), Is.False); + } + } + [Test] public void DelayedSelectsOutOfLimitTest05() { @@ -179,8 +302,8 @@ public void DelayedSelectsOutOfLimitTest05() using (var session = Domain.OpenSession()) using (var transaction = session.OpenTransaction()) { - var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(); - var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(); + var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(StorageLimit - 1); + var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(StorageLimit + 1); var result1 = (DelayedSequence) session.Query.ExecuteDelayed(q => q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, fittedIds))); @@ -196,6 +319,30 @@ public void DelayedSelectsOutOfLimitTest05() } } + [Test] + public async Task DelayedSelectsOutOfLimitAsyncTest05() + { + RequireLimit(); + + using (var session = await Domain.OpenSessionAsync()) + using (var transaction = session.OpenTransaction()) { + var fittedIds = Enumerable.Range(1, StorageLimit - 1).ToArray(StorageLimit - 1); + var idsOutOfRange = Enumerable.Range(1, StorageLimit + 1).ToArray(StorageLimit + 1); + + var result1 = (DelayedSequence) session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, fittedIds))); + + var result2 = session.Query.ExecuteDelayed(q => + q.All().Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, fittedIds))); + + _ = Assert.ThrowsAsync( + async () => (await session.Query.All() + .Where(e => e.Id.In(IncludeAlgorithm.ComplexCondition, idsOutOfRange)).AsAsync()).Run()); + Assert.That(result1.Any(), Is.True); + Assert.That(result2.Any(), Is.True); + } + } + [Test] public void InsertTest01() { From 591b67df2ab77e738ebef33ee429af07c1a951d2 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Wed, 23 Dec 2020 17:14:28 +0500 Subject: [PATCH 2/3] Applies SessionScope/Scope changes from master --- Orm/Xtensive.Orm/Core/Scope.cs | 47 ++++++++--------- Orm/Xtensive.Orm/Orm/Domain.cs | 28 +++++++--- Orm/Xtensive.Orm/Orm/Session.cs | 10 ++-- Orm/Xtensive.Orm/Orm/SessionScope.cs | 76 +++++++++++++++++++++++----- Orm/Xtensive.Orm/Orm/StorageNode.cs | 15 ++++-- Orm/Xtensive.Orm/Strings.Designer.cs | 14 ++++- Orm/Xtensive.Orm/Strings.resx | 5 +- 7 files changed, 142 insertions(+), 53 deletions(-) diff --git a/Orm/Xtensive.Orm/Core/Scope.cs b/Orm/Xtensive.Orm/Core/Scope.cs index 669ad5e2b8..4eca4cfb2c 100644 --- a/Orm/Xtensive.Orm/Core/Scope.cs +++ b/Orm/Xtensive.Orm/Core/Scope.cs @@ -143,36 +143,37 @@ protected virtual void Dispose(bool disposing) /// Current scope differs from this one. public void Dispose() { - bool bStop = false; Exception error = null; - while (!bStop) { - try { - if (currentScopeAsync==null) { - bStop = true; - throw new InvalidOperationException(Strings.ExScopeCantBeDisposed); - } - else if (currentScopeAsync.Value==this) { - bStop = true; - currentScopeAsync.Value.Dispose(true); - } - else { - currentScopeAsync.Value.Dispose(); + try { + while (true) { + try { + var currentScope = currentScopeAsync.Value; + if (currentScope == null) { + throw new InvalidOperationException(Strings.ExScopeCantBeDisposed); + } + + if (currentScope == this) { + currentScope.Dispose(true); + break; + } + + currentScope.Dispose(); } - } - catch (Exception e) { - if (error==null) + catch (Exception e) { error = e; - try { CoreLog.Error(e, Strings.LogScopeDisposeError); + break; } - catch {} } } - currentScopeAsync.Value = outerScope; - context = null; - outerScope = null; - if (error!=null) - throw error; + finally { + currentScopeAsync.Value = outerScope; + context = null; + outerScope = null; + if (error != null) { + throw error; + } + } } } } \ No newline at end of file diff --git a/Orm/Xtensive.Orm/Orm/Domain.cs b/Orm/Xtensive.Orm/Orm/Domain.cs index af3ea88dd3..4b224f5d46 100644 --- a/Orm/Xtensive.Orm/Orm/Domain.cs +++ b/Orm/Xtensive.Orm/Orm/Domain.cs @@ -326,11 +326,22 @@ public Task OpenSessionAsync(SessionType type, CancellationToken cancel /// public Task OpenSessionAsync(SessionConfiguration configuration, CancellationToken cancellationToken = default) { - return OpenSessionInternalAsync(configuration, null, - configuration.Supports(SessionOptions.AutoActivation), cancellationToken); + ArgumentValidator.EnsureArgumentNotNull(configuration, nameof(configuration)); + + SessionScope sessionScope = null; + try { + if (configuration.Supports(SessionOptions.AutoActivation)) { + sessionScope = new SessionScope(); + } + return OpenSessionInternalAsync(configuration, null, sessionScope, cancellationToken); + } + catch { + sessionScope?.Dispose(); + throw; + } } - internal async Task OpenSessionInternalAsync(SessionConfiguration configuration, StorageNode storageNode, bool activate, CancellationToken cancellationToken) + internal async Task OpenSessionInternalAsync(SessionConfiguration configuration, StorageNode storageNode, SessionScope sessionScope, CancellationToken cancellationToken) { ArgumentValidator.EnsureArgumentNotNull(configuration, nameof(configuration)); @@ -358,10 +369,13 @@ internal async Task OpenSessionInternalAsync(SessionConfiguration confi // connection become opened. session = new Session(this, storageNode, configuration, false); try { - await ((SqlSessionHandler)session.Handler).OpenConnectionAsync(cancellationToken).ContinueWith((t) => { - if (activate) - session.ActivateInternally(); - }, TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.ExecuteSynchronously).ConfigureAwait(false); + await ((SqlSessionHandler) session.Handler).OpenConnectionAsync(cancellationToken) + .ContinueWith(t => { + if (sessionScope != null) { + session.AttachToScope(sessionScope); + } + }, TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.ExecuteSynchronously) + .ConfigureAwait(false); } catch (OperationCanceledException) { session.DisposeSafely(); diff --git a/Orm/Xtensive.Orm/Orm/Session.cs b/Orm/Xtensive.Orm/Orm/Session.cs index 1eb3b9cb86..4ea34c641e 100644 --- a/Orm/Xtensive.Orm/Orm/Session.cs +++ b/Orm/Xtensive.Orm/Orm/Session.cs @@ -234,9 +234,10 @@ internal void EnsureNotDisposed() throw new ObjectDisposedException(Strings.ExSessionIsAlreadyDisposed); } - internal void ActivateInternally() + internal void AttachToScope(SessionScope sessionScope) { - disposableSet.Add(new SessionScope(this)); + sessionScope.Session = this; + _ = disposableSet.Add(sessionScope); } internal EnumerationContext CreateEnumerationContext() @@ -582,8 +583,9 @@ internal Session(Domain domain, StorageNode selectedStorageNode, SessionConfigur disableAutoSaveChanges = !configuration.Supports(SessionOptions.AutoSaveChanges); // Perform activation - if (activate) - ActivateInternally(); + if (activate) { + AttachToScope(new SessionScope()); + } // Query endpoint SystemQuery = Query = new QueryEndpoint(new QueryProvider(this)); diff --git a/Orm/Xtensive.Orm/Orm/SessionScope.cs b/Orm/Xtensive.Orm/Orm/SessionScope.cs index 9637a0d656..b7cc1ce79d 100644 --- a/Orm/Xtensive.Orm/Orm/SessionScope.cs +++ b/Orm/Xtensive.Orm/Orm/SessionScope.cs @@ -4,6 +4,8 @@ // Created by: Dmitri Maximov // Created: 2007.08.29 +using System; +using System.Threading; using Xtensive.Core; namespace Xtensive.Orm @@ -11,34 +13,84 @@ namespace Xtensive.Orm /// /// activation scope. /// - public sealed class SessionScope : Scope + public sealed class SessionScope : IDisposable // : Scope { + private static readonly AsyncLocal currentScopeAsync = new AsyncLocal(); + + private enum State + { + New, + Active, + Disposed + } + + private readonly SessionScope outerScope; + private Session session; + private State state; + /// /// Gets the current . /// - public static Session CurrentSession - { - get { return CurrentContext; } - } + public static Session CurrentSession => currentScopeAsync.Value?.Session; /// /// Gets the context of this scope. /// public Session Session { - get { return Context; } + get => state == State.Active ? session : outerScope?.Session; + internal set { + if (state != State.New) { + throw new InvalidOperationException(Strings.ExCantModifyActiveOrDisposedScope); + } + + state = State.Active; + session = value; + } } + /// + public void Dispose() + { + if (state == State.Disposed) { + return; + } + + var currentScope = currentScopeAsync.Value; + + while (currentScope != null) { + if (currentScope == this) { + currentScopeAsync.Value = outerScope; + state = State.Disposed; + session = null; + return; + } + + currentScope = currentScope.outerScope; + } + + throw new InvalidOperationException(Strings.ExScopeCantBeDisposed); + } // Constructors - /// - /// Initializes a new instance of this class. - /// - /// The session to activate. - public SessionScope(Session session) - : base(session) + internal SessionScope() + { + state = State.New; + + outerScope = currentScopeAsync.Value; + while (outerScope != null && outerScope.state != State.Active) { + outerScope = outerScope.outerScope; + } + + currentScopeAsync.Value = this; + } + + internal SessionScope(Session session) + : this() { + this.session = session; + state = State.Active; } } } \ No newline at end of file diff --git a/Orm/Xtensive.Orm/Orm/StorageNode.cs b/Orm/Xtensive.Orm/Orm/StorageNode.cs index 62914ed18e..486549f863 100644 --- a/Orm/Xtensive.Orm/Orm/StorageNode.cs +++ b/Orm/Xtensive.Orm/Orm/StorageNode.cs @@ -96,10 +96,17 @@ public Task OpenSessionAsync(SessionConfiguration configuration, Cancel { ArgumentValidator.EnsureArgumentNotNull(configuration, nameof(configuration)); - return domain.OpenSessionInternalAsync(configuration, - this, - configuration.Supports(SessionOptions.AllowSwitching), - cancellationToken); + SessionScope sessionScope = null; + try { + if (configuration.Supports(SessionOptions.AutoActivation)) { + sessionScope = new SessionScope(); + } + return domain.OpenSessionInternalAsync(configuration, this, sessionScope, cancellationToken); + } + catch { + sessionScope?.Dispose(); + throw; + } } // Constructors diff --git a/Orm/Xtensive.Orm/Strings.Designer.cs b/Orm/Xtensive.Orm/Strings.Designer.cs index 5d6169bfdb..6a87df93bf 100644 --- a/Orm/Xtensive.Orm/Strings.Designer.cs +++ b/Orm/Xtensive.Orm/Strings.Designer.cs @@ -1146,6 +1146,15 @@ internal static string ExCantMergeState { } } + /// + /// Looks up a localized string similar to Can't modify Active or Disposed scope.. + /// + internal static string ExCantModifyActiveOrDisposedScope { + get { + return ResourceManager.GetString("ExCantModifyActiveOrDisposedScope", resourceCulture); + } + } + /// /// Looks up a localized string similar to Can't open EnumerationScope, since there is no current CompilationContext.. /// @@ -6959,9 +6968,10 @@ internal static string ExUnableToCastNullValueToXUseXInstead { internal static string ExUnableToCastXToYAttemptToOverrideExistingFieldMap { get { return ResourceManager.GetString("ExUnableToCastXToYAttemptToOverrideExistingFieldMap", resourceCulture); - } + } } - + + /// /// Looks up a localized string similar to Unable to change command: it is already prepared.. /// internal static string ExUnableToChangeCommandItIsAlreadyPrepared { diff --git a/Orm/Xtensive.Orm/Strings.resx b/Orm/Xtensive.Orm/Strings.resx index 956d1c081c..226c2e0c07 100644 --- a/Orm/Xtensive.Orm/Strings.resx +++ b/Orm/Xtensive.Orm/Strings.resx @@ -3464,4 +3464,7 @@ Error: {1} Unable to prepare command: no parts registered. - + + Can't modify Active or Disposed scope. + + \ No newline at end of file From 536161f133ace98bb61472be56ffb5059463fea1 Mon Sep 17 00:00:00 2001 From: Alexey Kulakov Date: Wed, 23 Dec 2020 21:18:48 +0500 Subject: [PATCH 3/3] Fixes some issues discovered after new tests --- .../CommandProcessing/BatchingCommandProcessor.cs | 5 ++--- Orm/Xtensive.Orm/Orm/Session.QueryTasks.cs | 8 ++++---- Orm/Xtensive.Orm/Orm/Session.cs | 4 ++-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Orm/Xtensive.Orm/Orm/Providers/CommandProcessing/BatchingCommandProcessor.cs b/Orm/Xtensive.Orm/Orm/Providers/CommandProcessing/BatchingCommandProcessor.cs index 238dd0ab94..2108c73ab7 100644 --- a/Orm/Xtensive.Orm/Orm/Providers/CommandProcessing/BatchingCommandProcessor.cs +++ b/Orm/Xtensive.Orm/Orm/Providers/CommandProcessing/BatchingCommandProcessor.cs @@ -182,9 +182,7 @@ private Command ExecuteBatch(int numberOfTasks, QueryRequest lastRequest, Comman private async Task ExecuteBatchAsync(int numberOfTasks, QueryRequest lastRequest, CommandProcessorContext context, CancellationToken token) { - var shouldReturnReader = lastRequest!=null; - - if (numberOfTasks==0 && !shouldReturnReader) { + if (numberOfTasks==0 && lastRequest==null) { return null; } @@ -192,6 +190,7 @@ private async Task ExecuteBatchAsync(int numberOfTasks, QueryRequest la AllocateCommand(context); + var shouldReturnReader = false; try { while (numberOfTasks > 0 && tasksToProcess.Count > 0) { var task = tasksToProcess.Peek(); diff --git a/Orm/Xtensive.Orm/Orm/Session.QueryTasks.cs b/Orm/Xtensive.Orm/Orm/Session.QueryTasks.cs index faca2bec2b..075ccc0be7 100644 --- a/Orm/Xtensive.Orm/Orm/Session.QueryTasks.cs +++ b/Orm/Xtensive.Orm/Orm/Session.QueryTasks.cs @@ -53,9 +53,9 @@ internal async Task ExecuteDelayedUserQueriesAsync(bool skipPersist, Cance { token.ThrowIfCancellationRequested(); if (!skipPersist) - Persist(PersistReason.Other); + Persist(PersistReason.Query); token.ThrowIfCancellationRequested(); - return await ProcessUserDefinedDelayedQueriesAsync(token).ConfigureAwait(false); + return await ProcessUserDefinedDelayedQueriesAsync(false, token).ConfigureAwait(false); } private bool ProcessUserDefinedDelayedQueries(bool allowPartialExecution) @@ -84,13 +84,13 @@ private bool ProcessInternalDelayedQueries(bool allowPartialExecution) } } - private async Task ProcessUserDefinedDelayedQueriesAsync(CancellationToken token) + private async Task ProcessUserDefinedDelayedQueriesAsync(bool allowPartialExecution, CancellationToken token) { if (userDefinedQueryTasks.Count==0) return false; var aliveTasks = userDefinedQueryTasks.Where(t => t.LifetimeToken.IsActive).ToList(); userDefinedQueryTasks.Clear(); - await Handler.ExecuteQueryTasksAsync(aliveTasks, false, token).ConfigureAwait(false); + await Handler.ExecuteQueryTasksAsync(aliveTasks, allowPartialExecution, token).ConfigureAwait(false); return true; } } diff --git a/Orm/Xtensive.Orm/Orm/Session.cs b/Orm/Xtensive.Orm/Orm/Session.cs index 4ea34c641e..7f350f18a2 100644 --- a/Orm/Xtensive.Orm/Orm/Session.cs +++ b/Orm/Xtensive.Orm/Orm/Session.cs @@ -249,9 +249,9 @@ internal EnumerationContext CreateEnumerationContext() internal async Task CreateEnumerationContextForAsyncQuery(CancellationToken token) { - Persist(PersistReason.Other); + Persist(PersistReason.Query); token.ThrowIfCancellationRequested(); - await ProcessUserDefinedDelayedQueriesAsync(token).ConfigureAwait(false); + await ProcessUserDefinedDelayedQueriesAsync(true, token).ConfigureAwait(false); return new Providers.EnumerationContext(this, GetEnumerationContextOptions()); }