/// <summary> /// Asynchronously iterates over the input sequence and performs the specified action on each element of the <see cref="IAsyncQueryable{T}"/>. /// Return <see langword="true"/> from <paramref name="action"/> to cause the loop to gracefully break; <see langword="false"/> to continue looping. /// </summary> /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam> /// <param name="source">An <see cref="IAsyncQueryable{T}"/> containing items to operate on.</param> /// <param name="action">The action to perform each element. Return <see langword="true"/> to cause the loop to gracefully break.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns> /// <exception cref="ArgumentNullException"><paramref name="action"/> is null.</exception> public static async Task ForEachAsync <TSource>(this IAsyncQueryable <TSource> source, Func <TSource, bool> action, CancellationToken cancellationToken = default(CancellationToken)) { if (action == null) { throw new ArgumentNullException(nameof(action)); } while (await source.MoveNextAsync(cancellationToken).ConfigureAwait(false)) { bool breakRequested = false; foreach (var item in source.CurrentPage) { cancellationToken.ThrowIfCancellationRequested(); breakRequested |= action(item); if (breakRequested) { break; } } if (breakRequested) { break; } } }
/// <summary> /// Asynchronously returns the only element of a sequence, or a default value if the sequence is /// empty; this method throws an exception if there is more than one element in the sequence. /// </summary> /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam> /// <param name="source">An <see cref="IAsyncQueryable{T}"/> to return the single element of.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The single element of the input sequence, or <c>default(TSource)</c> if the sequence contains no elements.</returns> /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> /// <exception cref="System.InvalidOperationException"><paramref name="source"/> has more than one element.</exception> public static async Task <TSource> SingleOrDefaultAsync <TSource>(this IAsyncQueryable <TSource> source, CancellationToken cancellationToken = default(CancellationToken)) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (!await source.MoveNextAsync(cancellationToken).ConfigureAwait(false)) { return(default(TSource)); } return(source.CurrentPage.SingleOrDefault()); }
/// <summary> /// Asynchronously returns the only element of a sequence, and throws an exception if there is not exactly one element in the sequence. /// </summary> /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam> /// <param name="source">An <see cref="IAsyncQueryable{T}"/> to return the single element of.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The single element of the input sequence.</returns> /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> /// <exception cref="System.InvalidOperationException"><paramref name="source"/> has more than one element.</exception> public static async Task <TSource> SingleAsync <TSource>(this IAsyncQueryable <TSource> source, CancellationToken cancellationToken = default(CancellationToken)) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (!await source.MoveNextAsync(cancellationToken).ConfigureAwait(false)) { throw new InvalidOperationException("The sequence has no elements."); } return(source.CurrentPage.Single()); }
/// <summary> /// Asynchronously returns the input sequence as a <see cref="List{T}"/>. /// </summary> /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam> /// <param name="source">An <see cref="IAsyncQueryable{T}"/> to get items from.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>A list of all items from the input sequence.</returns> /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> public static async Task <List <TSource> > ToListAsync <TSource>(this IAsyncQueryable <TSource> source, CancellationToken cancellationToken = default(CancellationToken)) { if (source == null) { throw new ArgumentNullException(nameof(source)); } var results = new List <TSource>(); while (await source.MoveNextAsync(cancellationToken).ConfigureAwait(false)) { results.AddRange(source.CurrentPage); } return(results); }