diff --git a/ChangeLog/7.1.3_dev.txt b/ChangeLog/7.1.3_dev.txt index f2e3146bb8..e966b27f2d 100644 --- a/ChangeLog/7.1.3_dev.txt +++ b/ChangeLog/7.1.3_dev.txt @@ -1,4 +1,5 @@ [main] Addressed race condition issue with TranslatorState.NonVisitableExpressions [main] Improved working with nullable enum constants in queries +[main] Improved compatibility of .ToListAsync/.ToArrayAsync/.ToHashSetAsync/.AsAsyncEnumerable extension methods with EntitySet [postgresql] Improved database structucture extraction [postgresql] Addressed certain cases of decimal results of aggregate operations being unable to fit to .NET decimal \ No newline at end of file diff --git a/Orm/Xtensive.Orm.Tests/Storage/AsyncQueries/AsyncExtensionsTest.cs b/Orm/Xtensive.Orm.Tests/Storage/AsyncQueries/AsyncExtensionsTest.cs index 4d94159fb7..a8adae96da 100644 --- a/Orm/Xtensive.Orm.Tests/Storage/AsyncQueries/AsyncExtensionsTest.cs +++ b/Orm/Xtensive.Orm.Tests/Storage/AsyncQueries/AsyncExtensionsTest.cs @@ -1,4 +1,4 @@ -// Copyright (C) 2020 Xtensive LLC. +// Copyright (C) 2020-2024 Xtensive LLC. // This code is distributed under MIT license terms. // See the License.txt file in the project root for more information. @@ -100,7 +100,7 @@ public async Task AverageAsyncIntOnEmptySequenceExtensionTest(bool isClientProfi var emptyFactors = (await emptyQuery.ExecuteAsync()).ToList(); Assert.AreEqual(0, emptyFactors.Count); - Assert.ThrowsAsync(() => emptyQuery.AverageAsync()); + _ = Assert.ThrowsAsync(() => emptyQuery.AverageAsync()); } } @@ -127,7 +127,7 @@ public async Task AverageAsyncIntWithSelectorOnEmptySequenceExtensionTest(bool i var emptyFactors = (await emptyQuery.ExecuteAsync()).Select(stat => stat.IntFactor).ToList(); Assert.AreEqual(0, emptyFactors.Count); - Assert.ThrowsAsync(() => emptyQuery.AverageAsync(stat => stat.IntFactor)); + _ = Assert.ThrowsAsync(() => emptyQuery.AverageAsync(stat => stat.IntFactor)); } } @@ -242,7 +242,7 @@ public async Task AverageAsyncLongOnEmptySequenceExtensionTest(bool isClientProf var emptyFactors = (await emptyQuery.ExecuteAsync()).ToList(); Assert.AreEqual(0, emptyFactors.Count); - Assert.ThrowsAsync(() => emptyQuery.AverageAsync()); + _ = Assert.ThrowsAsync(() => emptyQuery.AverageAsync()); } } @@ -269,7 +269,7 @@ public async Task AverageAsyncLongWithSelectorOnEmptySequenceExtensionTest(bool var emptyFactors = (await emptyQuery.ExecuteAsync()).Select(stat => stat.LongFactor).ToList(); Assert.AreEqual(0, emptyFactors.Count); - Assert.ThrowsAsync(() => emptyQuery.AverageAsync(stat => stat.LongFactor)); + _ = Assert.ThrowsAsync(() => emptyQuery.AverageAsync(stat => stat.LongFactor)); } } @@ -384,7 +384,7 @@ public async Task AverageAsyncDoubleOnEmptySequenceExtensionTest(bool isClientPr var emptyFactors = (await emptyQuery.ExecuteAsync()).ToList(); Assert.AreEqual(0, emptyFactors.Count); - Assert.ThrowsAsync(() => emptyQuery.AverageAsync()); + _ = Assert.ThrowsAsync(() => emptyQuery.AverageAsync()); } } @@ -411,7 +411,7 @@ public async Task AverageAsyncDoubleWithSelectorOnEmptySequenceExtensionTest(boo var emptyFactors = (await emptyQuery.ExecuteAsync()).Select(stat => stat.DoubleFactor).ToList(); Assert.AreEqual(0, emptyFactors.Count); - Assert.ThrowsAsync(() => emptyQuery.AverageAsync(stat => stat.DoubleFactor)); + _ = Assert.ThrowsAsync(() => emptyQuery.AverageAsync(stat => stat.DoubleFactor)); } } @@ -526,7 +526,7 @@ public async Task AverageAsyncFloatOnEmptySequenceExtensionTest(bool isClientPro var emptyFactors = (await emptyQuery.ExecuteAsync()).ToList(); Assert.AreEqual(0, emptyFactors.Count); - Assert.ThrowsAsync(() => emptyQuery.AverageAsync()); + _ = Assert.ThrowsAsync(() => emptyQuery.AverageAsync()); } } @@ -553,7 +553,7 @@ public async Task AverageAsyncFloatWithSelectorOnEmptySequenceExtensionTest(bool var emptyFactors = (await emptyQuery.ExecuteAsync()).Select(stat => stat.FloatFactor).ToList(); Assert.AreEqual(0, emptyFactors.Count); - Assert.ThrowsAsync(() => emptyQuery.AverageAsync(stat => stat.FloatFactor)); + _ = Assert.ThrowsAsync(() => emptyQuery.AverageAsync(stat => stat.FloatFactor)); } } @@ -668,7 +668,7 @@ public async Task AverageAsyncDecimalOnEmptySequenceExtensionTest(bool isClientP var emptyFactors = (await emptyQuery.ExecuteAsync()).ToList(); Assert.AreEqual(0, emptyFactors.Count); - Assert.ThrowsAsync(() => emptyQuery.AverageAsync()); + _ = Assert.ThrowsAsync(() => emptyQuery.AverageAsync()); } } @@ -695,7 +695,7 @@ public async Task AverageAsyncDecimalWithSelectorOnEmptySequenceExtensionTest(bo var emptyFactors = (await emptyQuery.ExecuteAsync()).Select(stat => stat.DecimalFactor).ToList(); Assert.AreEqual(0, emptyFactors.Count); - Assert.ThrowsAsync(() => emptyQuery.AverageAsync(stat => stat.DecimalFactor)); + _ = Assert.ThrowsAsync(() => emptyQuery.AverageAsync(stat => stat.DecimalFactor)); } } @@ -867,7 +867,7 @@ public async Task FirstAsyncOnEmptySequenceExtensionTest(bool isClientProfile) await using var session = await OpenSessionAsync(Domain, isClientProfile); await using (OpenTransactionAsync(session, isClientProfile)) { var query = session.Query.All().Take(0); - Assert.ThrowsAsync(() => query.FirstAsync()); + _ = Assert.ThrowsAsync(() => query.FirstAsync()); } } @@ -888,7 +888,7 @@ public async Task FirstAsyncWithPredicateOnEmptySequenceExtensionTest(bool isCli await using var session = await OpenSessionAsync(Domain, isClientProfile); await using (OpenTransactionAsync(session, isClientProfile)) { var query = session.Query.All(); - Assert.ThrowsAsync(() => query.FirstAsync(teacher => teacher.Id < 0)); + _ = Assert.ThrowsAsync(() => query.FirstAsync(teacher => teacher.Id < 0)); } } @@ -955,7 +955,7 @@ public async Task LastAsyncOnEmptySequenceExtensionTest(bool isClientProfile) await using var session = await OpenSessionAsync(Domain, isClientProfile); await using (OpenTransactionAsync(session, isClientProfile)) { var query = session.Query.All().Take(0); - Assert.ThrowsAsync(() => query.LastAsync()); + _ = Assert.ThrowsAsync(() => query.LastAsync()); } } @@ -976,7 +976,7 @@ public async Task LastAsyncWithPredicateOnEmptySequenceExtensionTest(bool isClie await using var session = await OpenSessionAsync(Domain, isClientProfile); await using (OpenTransactionAsync(session, isClientProfile)) { var query = session.Query.All(); - Assert.ThrowsAsync(() => query.LastAsync(teacher => teacher.Id < 0)); + _ = Assert.ThrowsAsync(() => query.LastAsync(teacher => teacher.Id < 0)); } } @@ -1129,7 +1129,7 @@ public async Task MaxAsyncOnEmptySequenceExtensionTest(bool isClientProfile) .Select(stat => stat.IntFactor); var elements = query.ToList(); Assert.AreEqual(0, elements.Count); - Assert.ThrowsAsync(() => query.MaxAsync()); + _ = Assert.ThrowsAsync(() => query.MaxAsync()); } } @@ -1201,8 +1201,8 @@ public async Task MaxAsyncWithSelectorOnEmptySequenceExtensionTest(bool isClient var query = session.Query.All().Where(stat => stat.Id < 0); var elements = query.ToList(); Assert.AreEqual(0, elements.Count); - Assert.Throws(() => _ = elements.Max(stat => stat.IntFactor)); - Assert.ThrowsAsync(() => query.MaxAsync(stat => stat.IntFactor)); + _ = Assert.Throws(() => _ = elements.Max(stat => stat.IntFactor)); + _ = Assert.ThrowsAsync(() => query.MaxAsync(stat => stat.IntFactor)); } } @@ -1276,7 +1276,7 @@ public async Task MinAsyncOnEmptySequenceExtensionTest(bool isClientProfile) .Select(stat => stat.IntFactor); var elements = query.ToList(); Assert.AreEqual(0, elements.Count); - Assert.ThrowsAsync(() => query.MinAsync()); + _ = Assert.ThrowsAsync(() => query.MinAsync()); } } @@ -1348,8 +1348,8 @@ public async Task MinAsyncWithSelectorOnEmptySequenceExtensionTest(bool isClient var query = session.Query.All().Where(stat => stat.Id < 0); var elements = query.ToList(); Assert.AreEqual(0, elements.Count); - Assert.Throws(() => _ = elements.Min(stat => stat.IntFactor)); - Assert.ThrowsAsync(() => query.MinAsync(stat => stat.IntFactor)); + _ = Assert.Throws(() => _ = elements.Min(stat => stat.IntFactor)); + _ = Assert.ThrowsAsync(() => query.MinAsync(stat => stat.IntFactor)); } } @@ -1385,7 +1385,7 @@ public async Task SingleAsyncOnEmptySequenceExtensionTest(bool isClientProfile) await using var session = await OpenSessionAsync(Domain, isClientProfile); await using (OpenTransactionAsync(session, isClientProfile)) { var query = session.Query.All().Take(0); - Assert.ThrowsAsync(() => query.SingleAsync()); + _ = Assert.ThrowsAsync(() => query.SingleAsync()); } } @@ -1395,7 +1395,7 @@ public async Task SingleAsyncOnSequenceExtensionTest(bool isClientProfile) await using var session = await OpenSessionAsync(Domain, isClientProfile); await using (OpenTransactionAsync(session, isClientProfile)) { var query = session.Query.All(); - Assert.ThrowsAsync(() => query.SingleAsync()); + _ = Assert.ThrowsAsync(() => query.SingleAsync()); } } @@ -1416,7 +1416,7 @@ public async Task SingleAsyncWithPredicateOnEmptySequenceExtensionTest(bool isCl await using var session = await OpenSessionAsync(Domain, isClientProfile); await using (OpenTransactionAsync(session, isClientProfile)) { var query = session.Query.All(); - Assert.ThrowsAsync(() => query.SingleAsync(teacher => teacher.Id < 0)); + _ = Assert.ThrowsAsync(() => query.SingleAsync(teacher => teacher.Id < 0)); } } @@ -1426,7 +1426,7 @@ public async Task SingleAsyncWithPredicateOnSequenceExtensionTest(bool isClientP await using var session = await OpenSessionAsync(Domain, isClientProfile); await using (OpenTransactionAsync(session, isClientProfile)) { var query = session.Query.All(); - Assert.ThrowsAsync(() => query.SingleAsync(teacher => teacher.Gender==Gender.Male)); + _ = Assert.ThrowsAsync(() => query.SingleAsync(teacher => teacher.Gender==Gender.Male)); } } @@ -1459,7 +1459,7 @@ public async Task SingleOrDefaultAsyncOnSequenceExtensionTest(bool isClientProfi await using var session = await OpenSessionAsync(Domain, isClientProfile); await using (OpenTransactionAsync(session, isClientProfile)) { var query = session.Query.All(); - Assert.ThrowsAsync(() => query.SingleOrDefaultAsync()); + _ = Assert.ThrowsAsync(() => query.SingleOrDefaultAsync()); } } @@ -1490,7 +1490,7 @@ public async Task SingleOrDefaultAsyncWithPredicateOnSequenceExtensionTest(bool await using var session = await OpenSessionAsync(Domain, isClientProfile); await using (OpenTransactionAsync(session, isClientProfile)) { var query = session.Query.All(); - Assert.ThrowsAsync( + _ = Assert.ThrowsAsync( () => query.SingleOrDefaultAsync(teacher => teacher.Gender==Gender.Male)); } } @@ -2216,6 +2216,20 @@ public async Task ToListAsyncExtensionTest(bool isClientProfile) var allTeachers = query.ToList(); var allTeachersAsync = await query.ToListAsync(); Assert.IsTrue(allTeachers.SequenceEqual(allTeachersAsync)); + + var firstTeacher = allTeachers[0]; + var disceplines = firstTeacher.Disciplines.Where(d => d.Discepline != null).ToList(); + var disceplinesAsync = await firstTeacher.Disciplines.Where(d => d.Discepline != null).ToListAsync(); + Assert.That(disceplines.Count, Is.GreaterThan(0)); + Assert.That(disceplinesAsync.Count, Is.EqualTo(disceplines.Count)); + Assert.That(disceplines.Except(disceplinesAsync), Is.Empty); + + var secondTeacher = allTeachers[1]; + disceplines = secondTeacher.Disciplines.ToList(); + disceplinesAsync = await secondTeacher.Disciplines.ToListAsync(); + Assert.That(disceplines.Count, Is.GreaterThan(0)); + Assert.That(disceplinesAsync.Count, Is.EqualTo(disceplines.Count)); + Assert.That(disceplines.Except(disceplinesAsync), Is.Empty); } } @@ -2230,6 +2244,20 @@ public async Task ToArrayAsyncExtensionTest(bool isClientProfile) var allTeachers = query.ToArray(); var allTeachersAsync = await query.ToArrayAsync(); Assert.IsTrue(allTeachers.SequenceEqual(allTeachersAsync)); + + var firstTeacher = allTeachers[0]; + var disceplines = firstTeacher.Disciplines.Where(d => d.Discepline != null).ToArray(); + var disceplinesAsync = await firstTeacher.Disciplines.Where(d => d.Discepline != null).ToArrayAsync(); + Assert.That(disceplines.Length, Is.GreaterThan(0)); + Assert.That(disceplinesAsync.Length, Is.EqualTo(disceplines.Length)); + Assert.That(disceplines.Except(disceplinesAsync), Is.Empty); + + var secondTeacher = allTeachers[1]; + disceplines = secondTeacher.Disciplines.ToArray(); + disceplinesAsync = await secondTeacher.Disciplines.ToArrayAsync(); + Assert.That(disceplines.Length, Is.GreaterThan(0)); + Assert.That(disceplinesAsync.Length, Is.EqualTo(disceplines.Length)); + Assert.That(disceplines.Except(disceplinesAsync), Is.Empty); } } @@ -2247,6 +2275,19 @@ public async Task ToDictionaryAsyncWithKeySelectorExtensionTest(bool isClientPro foreach (var teacherId in allTeachers.Keys) { Assert.AreEqual(allTeachers[teacherId], allTeachersAsync[teacherId]); } + + var firstTeacher = allTeachers.Values.First(); + var disceplines = firstTeacher.Disciplines.Where(d => d.Discepline != null).ToDictionary(d => d.Course.Id); + var disceplinesAsync = await firstTeacher.Disciplines.Where(d => d.Discepline != null).ToDictionaryAsync(d => d.Course.Id); + Assert.That(disceplines.Count, Is.GreaterThan(0)); + Assert.That(disceplinesAsync.Count, Is.EqualTo(disceplines.Count)); + Assert.That(disceplines.Except(disceplinesAsync), Is.Empty); + + disceplines = firstTeacher.Disciplines.ToDictionary(d => d.Course.Id); + disceplinesAsync = await firstTeacher.Disciplines.ToDictionaryAsync(d => d.Course.Id); + Assert.That(disceplines.Count, Is.GreaterThan(0)); + Assert.That(disceplinesAsync.Count, Is.EqualTo(disceplines.Count)); + Assert.That(disceplines.Except(disceplinesAsync), Is.Empty); } } @@ -2262,6 +2303,20 @@ public async Task ToDictionaryAsyncWithKeyValueSelectorsExtensionTest(bool isCli foreach (var teacherId in allTeachers.Keys) { Assert.AreEqual(allTeachers[teacherId], allTeachersAsync[teacherId]); } + + var firstTeacher = session.Query.All().First(); + var disceplines = firstTeacher.Disciplines.Where(d => d.Discepline != null).ToDictionary(d => d.Course.Id, d => d.Discepline.Id); + var disceplinesAsync = await firstTeacher.Disciplines.Where(d => d.Discepline != null).ToDictionaryAsync(d => d.Course.Id, d => d.Discepline.Id); + Assert.That(disceplines.Count, Is.GreaterThan(0)); + Assert.That(disceplinesAsync.Count, Is.EqualTo(disceplines.Count)); + Assert.That(disceplines.Except(disceplinesAsync), Is.Empty); + + + disceplines = firstTeacher.Disciplines.ToDictionary(d => d.Course.Id, d => d.Discepline.Id); + disceplinesAsync = await firstTeacher.Disciplines.ToDictionaryAsync(d => d.Course.Id, d => d.Discepline.Id); + Assert.That(disceplines.Count, Is.GreaterThan(0)); + Assert.That(disceplinesAsync.Count, Is.EqualTo(disceplines.Count)); + Assert.That(disceplines.Except(disceplinesAsync), Is.Empty); } } @@ -2279,6 +2334,19 @@ public async Task ToHashSetAsyncExtensionTest(bool isClientProfile) foreach (var teacher in allTeachers) { Assert.IsTrue(allTeachersAsync.Contains(teacher)); } + + var firstTeacher = session.Query.All().First(); + var disceplines = firstTeacher.Disciplines.Where(d => d.Discepline != null).ToHashSet(); + var disceplinesAsync = await firstTeacher.Disciplines.Where(d => d.Discepline != null).ToHashSetAsync(); + Assert.That(disceplines.Count, Is.GreaterThan(0)); + Assert.That(disceplinesAsync.Count, Is.EqualTo(disceplines.Count)); + Assert.That(disceplines.Except(disceplinesAsync), Is.Empty); + + disceplines = firstTeacher.Disciplines.ToHashSet(); + disceplinesAsync = await firstTeacher.Disciplines.ToHashSetAsync(); + Assert.That(disceplines.Count, Is.GreaterThan(0)); + Assert.That(disceplinesAsync.Count, Is.EqualTo(disceplines.Count)); + Assert.That(disceplines.Except(disceplinesAsync), Is.Empty); } } @@ -2297,6 +2365,41 @@ public async Task ToLookupAsyncExtensionTest(bool isClientProfile) Assert.IsTrue(grouping.OrderBy(teacher => teacher.Id) .SequenceEqual(teachersByGenderAsync[grouping.Key].OrderBy(teacher => teacher.Id))); } + + var firstTeacher = session.Query.All().First(); + var disceplines = firstTeacher.Disciplines.Where(d => d.Discepline != null).ToLookup(d => d.Discepline.Id); + var disceplinesAsync = await firstTeacher.Disciplines.Where(d => d.Discepline != null).ToLookupAsync(d => d.Discepline.Id); + Assert.That(disceplines.Count, Is.GreaterThan(0)); + Assert.That(disceplinesAsync.Count, Is.EqualTo(disceplines.Count)); + var zipped = disceplines + .Zip(disceplinesAsync, + (first, second) => new { + FirstKey = first.Key, + FirstSeq = first.AsEnumerable(), + SecondKey = second.Key, + SecondSeq = second.AsEnumerable() + }); + foreach (var pair in zipped) { + Assert.That(pair.FirstKey, Is.EqualTo(pair.SecondKey)); + Assert.That(pair.FirstSeq.Except(pair.SecondSeq), Is.Empty); + } + + disceplines = firstTeacher.Disciplines.ToLookup(d => d.Discepline.Id); + disceplinesAsync = await firstTeacher.Disciplines.ToLookupAsync(d => d.Discepline.Id); + Assert.That(disceplines.Count, Is.GreaterThan(0)); + Assert.That(disceplinesAsync.Count, Is.EqualTo(disceplines.Count)); + zipped = disceplines + .Zip(disceplinesAsync, + (first, second) => new { + FirstKey = first.Key, + FirstSeq = first.AsEnumerable(), + SecondKey = second.Key, + SecondSeq = second.AsEnumerable() + }); + foreach (var pair in zipped) { + Assert.That(pair.FirstKey, Is.EqualTo(pair.SecondKey)); + Assert.That(pair.FirstSeq.Except(pair.SecondSeq), Is.Empty); + } } } @@ -2313,6 +2416,41 @@ public async Task ToLookupAsyncWithValueSelectorExtensionTest(bool isClientProfi Assert.IsTrue(grouping.OrderBy(teacherId => teacherId) .SequenceEqual(teachersByGenderAsync[grouping.Key].OrderBy(teacherId => teacherId))); } + + var firstTeacher = session.Query.All().First(); + var disceplines = firstTeacher.Disciplines.Where(d => d.Discepline != null).ToLookup(d => d.Discepline.Id, d => d.Course.Id); + var disceplinesAsync = await firstTeacher.Disciplines.Where(d => d.Discepline != null).ToLookupAsync(d => d.Discepline.Id, d => d.Course.Id); + Assert.That(disceplines.Count, Is.GreaterThan(0)); + Assert.That(disceplinesAsync.Count, Is.EqualTo(disceplines.Count)); + var zipped = disceplines + .Zip(disceplinesAsync, + (first, second) => new { + FirstKey = first.Key, + FirstSeq = first.AsEnumerable(), + SecondKey = second.Key, + SecondSeq = second.AsEnumerable() + }); + foreach (var pair in zipped) { + Assert.That(pair.FirstKey, Is.EqualTo(pair.SecondKey)); + Assert.That(pair.FirstSeq.Except(pair.SecondSeq), Is.Empty); + } + + disceplines = firstTeacher.Disciplines.ToLookup(d => d.Discepline.Id, d => d.Course.Id); + disceplinesAsync = await firstTeacher.Disciplines.ToLookupAsync(d => d.Discepline.Id, d => d.Course.Id); + Assert.That(disceplines.Count, Is.GreaterThan(0)); + Assert.That(disceplinesAsync.Count, Is.EqualTo(disceplines.Count)); + zipped = disceplines + .Zip(disceplinesAsync, + (first, second) => new { + FirstKey = first.Key, + FirstSeq = first.AsEnumerable(), + SecondKey = second.Key, + SecondSeq = second.AsEnumerable() + }); + foreach (var pair in zipped) { + Assert.That(pair.FirstKey, Is.EqualTo(pair.SecondKey)); + Assert.That(pair.FirstSeq.Except(pair.SecondSeq), Is.Empty); + } } } } diff --git a/Orm/Xtensive.Orm/Orm/QueryableExtensions.Async.cs b/Orm/Xtensive.Orm/Orm/QueryableExtensions.Async.cs index 8338ef715d..0d5e4ced95 100644 --- a/Orm/Xtensive.Orm/Orm/QueryableExtensions.Async.cs +++ b/Orm/Xtensive.Orm/Orm/QueryableExtensions.Async.cs @@ -1,4 +1,4 @@ -// Copyright (C) 2020 Xtensive LLC. +// Copyright (C) 2020-2024 Xtensive LLC. // This code is distributed under MIT license terms. // See the License.txt file in the project root for more information. @@ -21,12 +21,42 @@ namespace Xtensive.Orm /// public static partial class QueryableExtensions { + /// + /// A wrapper to transform non-, yet based on , + /// implementation, such as , into . + /// + private sealed class QueryAsAsyncEnumerable : IAsyncEnumerable + { + private readonly QueryProvider queryProvider; + private readonly Expression expression; + + /// + public async IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + var result = await queryProvider.ExecuteSequenceAsync(expression, cancellationToken).ConfigureAwait(false); + var asyncSource = result.AsAsyncEnumerable().WithCancellation(cancellationToken).ConfigureAwait(false); + await foreach (var element in asyncSource) { + yield return element; + } + } + + public QueryAsAsyncEnumerable(QueryProvider queryProvider, Expression expression) + { + this.queryProvider = queryProvider; + this.expression = expression; + } + } + /// /// Asynchronously determines whether all the elements of a sequence satisfy a condition. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of . /// An whose elements to test for a condition. /// A function to test each element for a condition. @@ -46,9 +76,13 @@ public static Task AllAsync(this IQueryable source, /// /// Asynchronously determines whether a sequence contains any elements. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// An to check for being empty. /// A to observe while waiting for the task to complete. @@ -65,9 +99,13 @@ public static Task AnyAsync(this IQueryable source, /// /// Asynchronously determines whether any element of a sequence satisfies a condition. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// An whose elements to test for a condition. /// A function to test each element for a condition. @@ -85,14 +123,20 @@ public static Task AnyAsync(this IQueryable source, WellKnownMembers.Queryable.AnyWithPredicate, source, predicate, cancellationToken); } + #region AverageAsync + // Average /// /// Asynchronously computes the average of a sequence of values. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// A sequence of values to calculate the average of. /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. The task result contains the @@ -109,9 +153,13 @@ public static Task AverageAsync(this IQueryable source, /// /// Asynchronously computes the average of a sequence of values. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// A sequence of values to calculate the average of. /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. The task result contains the @@ -129,9 +177,13 @@ public static Task AverageAsync(this IQueryable source, /// Asynchronously computes the average of a sequence of values that is obtained /// by invoking a projection function on each element of the input sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// A sequence of values to calculate the average of. /// A projection function to apply to each element. @@ -153,9 +205,13 @@ public static Task AverageAsync(this IQueryable source /// Asynchronously computes the average of a sequence of values that is obtained /// by invoking a projection function on each element of the input sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// A sequence of values to calculate the average of. /// A projection function to apply to each element. @@ -178,9 +234,13 @@ public static Task AverageAsync(this IQueryable source /// /// Asynchronously computes the average of a sequence of values. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// A sequence of values to calculate the average of. /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. The task result contains the @@ -197,9 +257,13 @@ public static Task AverageAsync(this IQueryable source, /// /// Asynchronously computes the average of a sequence of values. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// A sequence of values to calculate the average of. /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. The task result contains the @@ -217,9 +281,13 @@ public static Task AverageAsync(this IQueryable source, /// Asynchronously computes the average of a sequence of values that is obtained /// by invoking a projection function on each element of the input sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// A sequence of values to calculate the average of. /// A projection function to apply to each element. @@ -241,9 +309,13 @@ public static Task AverageAsync(this IQueryable source /// Asynchronously computes the average of a sequence of values that is obtained /// by invoking a projection function on each element of the input sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// A sequence of values to calculate the average of. /// A projection function to apply to each element. @@ -266,9 +338,13 @@ public static Task AverageAsync(this IQueryable source /// /// Asynchronously computes the average of a sequence of values. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// A sequence of values to calculate the average of. /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. The task result contains the @@ -285,9 +361,13 @@ public static Task AverageAsync(this IQueryable source, /// /// Asynchronously computes the average of a sequence of values. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// A sequence of values to calculate the average of. /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. The task result contains the @@ -305,9 +385,13 @@ public static Task AverageAsync(this IQueryable source, /// Asynchronously computes the average of a sequence of values that is obtained /// by invoking a projection function on each element of the input sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// A sequence of values to calculate the average of. /// A projection function to apply to each element. @@ -329,9 +413,13 @@ public static Task AverageAsync(this IQueryable source /// Asynchronously computes the average of a sequence of values that is obtained /// by invoking a projection function on each element of the input sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// A sequence of values to calculate the average of. /// A projection function to apply to each element. @@ -354,9 +442,13 @@ public static Task AverageAsync(this IQueryable source /// /// Asynchronously computes the average of a sequence of values. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// A sequence of values to calculate the average of. /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. The task result contains the @@ -373,9 +465,13 @@ public static Task AverageAsync(this IQueryable source, /// /// Asynchronously computes the average of a sequence of values. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// A sequence of values to calculate the average of. /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. The task result contains the @@ -393,9 +489,13 @@ public static Task AverageAsync(this IQueryable source, /// Asynchronously computes the average of a sequence of values that is obtained /// by invoking a projection function on each element of the input sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// A sequence of values to calculate the average of. /// A projection function to apply to each element. @@ -417,9 +517,13 @@ public static Task AverageAsync(this IQueryable source, /// Asynchronously computes the average of a sequence of values that is obtained /// by invoking a projection function on each element of the input sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// A sequence of values to calculate the average of. /// A projection function to apply to each element. @@ -442,9 +546,13 @@ public static Task AverageAsync(this IQueryable source, /// /// Asynchronously computes the average of a sequence of values. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// A sequence of values to calculate the average of. /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. The task result contains the @@ -461,9 +569,13 @@ public static Task AverageAsync(this IQueryable source, /// /// Asynchronously computes the average of a sequence of values. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// A sequence of values to calculate the average of. /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. The task result contains the @@ -481,9 +593,13 @@ public static Task AverageAsync(this IQueryable source, /// Asynchronously computes the average of a sequence of values that is obtained /// by invoking a projection function on each element of the input sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// A sequence of values to calculate the average of. /// A projection function to apply to each element. @@ -505,9 +621,13 @@ public static Task AverageAsync(this IQueryable sourc /// Asynchronously computes the average of a sequence of values that is obtained /// by invoking a projection function on each element of the input sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// A sequence of values to calculate the average of. /// A projection function to apply to each element. @@ -525,14 +645,20 @@ public static Task AverageAsync(this IQueryable sourc source, selector, cancellationToken); } + #endregion + // Contains /// /// Asynchronously determines whether a sequence contains a specified element. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// An to return the ssingle element of. /// The object to locate in the sequence. @@ -548,14 +674,18 @@ public static Task ContainsAsync(this IQueryable source, source, Expression.Constant(item, typeof(TSource)), cancellationToken); } - // Count + #region Count /// /// Asynchronously returns the number of elements in a sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// An that contains elements to be counted. /// A to observe while waiting for the task to complete. @@ -572,9 +702,13 @@ public static Task CountAsync(this IQueryable source, /// /// Asynchronously returns the number of elements in a sequence that satisfy a condition. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// An that contains elements to be counted. /// A function to test each element for a condition. @@ -591,14 +725,22 @@ public static Task CountAsync(this IQueryable source, source, predicate, cancellationToken); } + #endregion + + #region First, FirstOrDefault + // First /// /// Asynchronously returns the first element of a sequence /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// An to return the first element of. /// A to observe while waiting for the task to complete. @@ -615,9 +757,13 @@ public static Task FirstAsync(this IQueryable source, /// /// Asynchronously returns the first element of a sequence that satisfies a specified condition. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// An to return the first element of. /// A function to test each element for a condition. @@ -640,9 +786,13 @@ public static Task FirstAsync(this IQueryable source, /// Asynchronously returns the first element of a sequence, or a default value if /// the sequence contains no elements. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// An to return the first element of. /// A to observe while waiting for the task to complete. @@ -660,9 +810,13 @@ public static Task FirstOrDefaultAsync(this IQueryable - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// An to return the first element of. /// A function to test each element for a condition. @@ -680,14 +834,21 @@ public static Task FirstOrDefaultAsync(this IQueryable /// Asynchronously returns the last element of a sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// An to return the last element of. /// A to observe while waiting for the task to complete. @@ -704,9 +865,13 @@ public static Task LastAsync(this IQueryable source, /// /// Asynchronously returns the last element of a sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// An to return the last element of. /// A function to test each element for a condition. @@ -729,9 +894,13 @@ public static Task LastAsync(this IQueryable source, /// Asynchronously returns the last element of a sequence, or a default value if /// the sequence contains no elements. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// An to return the last element of. /// A to observe while waiting for the task to complete. @@ -749,9 +918,13 @@ public static Task LastOrDefaultAsync(this IQueryable /// Asynchronously returns the last element of a sequence that satisfies a specified /// condition or a default value if no such element is found. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// An to return the last element of. /// A function to test each element for a condition. @@ -769,15 +942,21 @@ public static Task LastOrDefaultAsync(this IQueryable source, predicate, cancellationToken); } - // LongCount + #endregion + + #region LongCount /// /// Asynchronously returns an System.Int64 that represents the number of elements /// in a sequence that satisfy a condition. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// An that contains the elements to be counted. /// A to observe while waiting for the task to complete. @@ -795,9 +974,13 @@ public static Task LongCountAsync(this IQueryable source /// Asynchronously returns an System.Int64 that represents the number of elements /// in a sequence that satisfy a condition. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// An that contains the elements to be counted. /// A function to test each element for a condition. @@ -815,14 +998,22 @@ public static Task LongCountAsync(this IQueryable source source, predicate, cancellationToken); } + #endregion + + #region Min, Max + // Max /// /// Asynchronously returns the maximum value of a sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// An that contains the elements ot determine the maximum of. /// A to observe while waiting for the task to complete. @@ -840,9 +1031,13 @@ public static Task MaxAsync(this IQueryable source, /// Asynchronously invokes a projection function on each element of a sequence and /// returns the maximum resulting value. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// he type of the value returned by the function represented by selector. /// An that contains the elements ot determine the maximum of. @@ -865,9 +1060,13 @@ public static Task MaxAsync(this IQueryable /// /// Asynchronously returns the minimum value of a sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// An that contains the elements ot determine the minimum of. /// A to observe while waiting for the task to complete. @@ -881,12 +1080,16 @@ public static Task MinAsync(this IQueryable source, } /// - /// synchronously invokes a projection function on each element of a sequence and + /// Asynchronously invokes a projection function on each element of a sequence and /// returns the minimum resulting value. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// The type of the value returned by the function represented by selector. /// An that contains the elements ot determine the minimum of. @@ -903,15 +1106,23 @@ public static Task MinAsync(this IQueryable source, selector, cancellationToken); } + #endregion + + #region Single, SingleOrDefault + // Single /// /// Asynchronously returns the only element of a sequence that satisfies a specified /// condition, and throws an exception if more than one such element exists. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// An to return the single element of. /// A to observe while waiting for the task to complete. @@ -929,9 +1140,13 @@ public static Task SingleAsync(this IQueryable source /// Asynchronously returns the only element of a sequence that satisfies a specified /// condition, and throws an exception if more than one such element exists. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// An to return the single element of. /// A function to test an element for a condition. @@ -955,9 +1170,13 @@ public static Task SingleAsync(this IQueryable source /// the sequence is empty; this method throws an exception if there is more than /// one element in the sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// An to return the single element of. /// A to observe while waiting for the task to complete. @@ -978,9 +1197,13 @@ public static Task SingleOrDefaultAsync(this IQueryable - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// An to return the single element of. /// A function to test an element for a condition. @@ -998,14 +1221,22 @@ public static Task SingleOrDefaultAsync(this IQueryable /// /// Asynchronously computes the sum of a sequence of values. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// A sequence of values to calculate the sum of. /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. The task result contains the @@ -1022,9 +1253,13 @@ public static Task SumAsync(this IQueryable source, /// /// Asynchronously computes the sum of a sequence of values. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// A sequence of values to calculate the sum of. /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. The task result contains the @@ -1042,9 +1277,13 @@ public static Task SumAsync(this IQueryable source, /// Asynchronously computes the sum of the sequence of values that is obtained by /// invoking a projection function on each element of the input sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// A sequence of values of type . /// A projection function to apply to each element. @@ -1066,9 +1305,13 @@ public static Task SumAsync(this IQueryable source, /// Asynchronously computes the sum of the sequence of values that is obtained by /// invoking a projection function on each element of the input sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// A sequence of values of type . /// A projection function to apply to each element. @@ -1091,9 +1334,13 @@ public static Task SumAsync(this IQueryable source, /// /// Asynchronously computes the sum of a sequence of values. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// A sequence of values to calculate the sum of. /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. The task result contains the @@ -1110,9 +1357,13 @@ public static Task SumAsync(this IQueryable source, /// /// Asynchronously computes the sum of a sequence of values. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// A sequence of values to calculate the sum of. /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. The task result contains the @@ -1130,9 +1381,13 @@ public static Task SumAsync(this IQueryable source, /// Asynchronously computes the sum of the sequence of values that is obtained by /// invoking a projection function on each element of the input sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// A sequence of values of type . /// A projection function to apply to each element. @@ -1154,9 +1409,13 @@ public static Task SumAsync(this IQueryable source, /// Asynchronously computes the sum of the sequence of values that is obtained by /// invoking a projection function on each element of the input sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// A sequence of values of type . /// A projection function to apply to each element. @@ -1179,9 +1438,13 @@ public static Task SumAsync(this IQueryable source, /// /// Asynchronously computes the sum of a sequence of values. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// A sequence of values to calculate the sum of. /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. The task result contains the @@ -1198,9 +1461,13 @@ public static Task SumAsync(this IQueryable source, /// /// Asynchronously computes the sum of a sequence of values. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// A sequence of values to calculate the sum of. /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. The task result contains the @@ -1218,9 +1485,13 @@ public static Task SumAsync(this IQueryable source, /// Asynchronously computes the sum of the sequence of values that is obtained by /// invoking a projection function on each element of the input sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// A sequence of values of type . /// A projection function to apply to each element. @@ -1242,9 +1513,13 @@ public static Task SumAsync(this IQueryable source, /// Asynchronously computes the sum of the sequence of values that is obtained by /// invoking a projection function on each element of the input sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// A sequence of values of type . /// A projection function to apply to each element. @@ -1267,9 +1542,13 @@ public static Task SumAsync(this IQueryable source, /// /// Asynchronously computes the sum of a sequence of values. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// A sequence of values to calculate the sum of. /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. The task result contains the @@ -1286,9 +1565,13 @@ public static Task SumAsync(this IQueryable source, /// /// Asynchronously computes the sum of a sequence of values. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// A sequence of values to calculate the sum of. /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. The task result contains the @@ -1306,9 +1589,13 @@ public static Task SumAsync(this IQueryable source, /// Asynchronously computes the sum of the sequence of values that is obtained by /// invoking a projection function on each element of the input sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// A sequence of values of type . /// A projection function to apply to each element. @@ -1330,9 +1617,13 @@ public static Task SumAsync(this IQueryable source, /// Asynchronously computes the sum of the sequence of values that is obtained by /// invoking a projection function on each element of the input sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// A sequence of values of type . /// A projection function to apply to each element. @@ -1355,9 +1646,13 @@ public static Task SumAsync(this IQueryable source, /// /// Asynchronously computes the sum of a sequence of values. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// A sequence of values to calculate the sum of. /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. The task result contains the @@ -1374,9 +1669,13 @@ public static Task SumAsync(this IQueryable source, /// /// Asynchronously computes the sum of a sequence of values. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// A sequence of values to calculate the sum of. /// A to observe while waiting for the task to complete. /// A task that represents the asynchronous operation. The task result contains the @@ -1394,9 +1693,13 @@ public static Task SumAsync(this IQueryable source, /// Asynchronously computes the sum of the sequence of values that is obtained by /// invoking a projection function on each element of the input sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// A sequence of values of type . /// A projection function to apply to each element. @@ -1418,9 +1721,13 @@ public static Task SumAsync(this IQueryable source, /// Asynchronously computes the sum of the sequence of values that is obtained by /// invoking a projection function on each element of the input sequence. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// A sequence of values of type . /// A projection function to apply to each element. @@ -1438,7 +1745,9 @@ public static Task SumAsync(this IQueryable source, source, selector, cancellationToken); } - // Collection methods + #endregion + + #region Collection methods private static readonly MethodInfo TupleCreateMethod = typeof(Tuple).GetMethods(BindingFlags.Public | BindingFlags.Static) @@ -1448,9 +1757,13 @@ public static Task SumAsync(this IQueryable source, /// Asynchronously creates a from an /// by enumerating it asynchronously. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// An to create a from. /// A to observe while waiting for the task to complete. @@ -1472,9 +1785,13 @@ public static async Task> ToListAsync(this IQueryable System.Linq.IQueryable`1 /// by enumerating it asynchronously. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// An to create an array from. /// A to observe while waiting for the task to complete. @@ -1488,9 +1805,13 @@ public static async Task ToArrayAsync(this IQueryable from an /// by enumerating it asynchronously according to a specified key selector function. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// >The type of the key returned by . /// The type of the elements of source. /// An to create a from. @@ -1522,9 +1843,13 @@ public static async Task> ToDictionaryAsync from an /// by enumerating it asynchronously according to a specified key selector and value selector functions. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// >The type of the key returned by . /// >The type of the key returned by . /// The type of the elements of source. @@ -1560,9 +1885,13 @@ public static async Task> ToDictionaryAsync from an /// by enumerating it asynchronously. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the elements of source. /// An to create a from. /// A to observe while waiting for the task to complete. @@ -1574,7 +1903,7 @@ public static async Task> ToHashSetAsync(this IQueryab var hashSet = new HashSet(); var asyncSource = source.AsAsyncEnumerable().WithCancellation(cancellationToken).ConfigureAwait(false); await foreach (var element in asyncSource) { - hashSet.Add(element); + _ = hashSet.Add(element); } return hashSet; @@ -1584,9 +1913,13 @@ public static async Task> ToHashSetAsync(this IQueryab /// Asynchronously creates a from an /// by enumerating it asynchronously according to a specified key selector function. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the key returned by . /// The type of the elements of source. /// An to create a from. @@ -1613,9 +1946,13 @@ public static async Task> ToLookupAsync(th /// by enumerating it asynchronously according to a specified key selector and an /// element selector function. /// - /// Multiple active operations in the same session instance are not supported. Use + /// + /// Multiple active operations in the same session instance are not supported. Use /// to ensure that all asynchronous operations have completed before calling - /// another method in this session. + /// another method in this session. + /// Notice that operation executes query so with some session options (like ) + /// result may not include newly created or locally removed entities or their data. Save local changes for them to be taken into account. + /// /// The type of the key returned by . /// The type of the value returned by . /// The type of the elements of source. @@ -1641,6 +1978,8 @@ public static async Task> ToLookupAsync tuple.Item1, tuple => tuple.Item2); } + #endregion + /// /// Returns an which can be enumerated asynchronously. /// @@ -1654,8 +1993,12 @@ public static IAsyncEnumerable AsAsyncEnumerable(this IQueryab { ArgumentValidator.EnsureArgumentNotNull(source, nameof(source)); - if (source is IAsyncEnumerable asyncEnumerable) { - return asyncEnumerable; + if (source is IAsyncEnumerable nativeAsyncEnumerable) { + return nativeAsyncEnumerable; + } + + if (source.Provider is QueryProvider doProvider) { + return new QueryAsAsyncEnumerable(doProvider, source.Expression); } throw new InvalidOperationException("Query can't be executed asynchronously.");