/// <summary> /// Asynchronously returns the first element of a sequence, or a default value if the sequence contains no elements. /// </summary> /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam> /// <param name="source">The <see cref="IAsyncQueryable{T}"/> to return the first element of.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns><c>default(TSource)</c> if <paramref name="source"/> is empty; otherwise, the first element in <paramref name="source"/>.</returns> /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> public static async Task <TSource> FirstOrDefaultAsync <TSource>(this IAsyncQueryable <TSource> source, CancellationToken cancellationToken = default(CancellationToken)) { if (source == null) { throw new ArgumentNullException(nameof(source)); } var sourceLimitQuery = source.Take(1); if (!await sourceLimitQuery.MoveNextAsync(cancellationToken).ConfigureAwait(false)) { return(default(TSource)); } return(sourceLimitQuery.CurrentPage.FirstOrDefault()); }
/// <summary> /// Asynchronously returns the number of elements in a sequence. /// </summary> /// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam> /// <param name="source">The <see cref="IAsyncQueryable{T}"/> that contains the elements to be counted.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The number of elements in the input sequence.</returns> /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> /// <exception cref="OverflowException">The number of elements in <paramref name="source"/> is larger than <see cref="int.MaxValue"/>.</exception> /// <exception cref="System.InvalidOperationException">The underlying provider does not support this operation.</exception> public static async Task <long> CountAsync <TSource>(this IAsyncQueryable <TSource> source, CancellationToken cancellationToken = default(CancellationToken)) { if (source == null) { throw new ArgumentNullException(nameof(source)); } var sourceLimitQuery = source.Take(1); if (!await sourceLimitQuery.MoveNextAsync(cancellationToken).ConfigureAwait(false)) { return(0); } var collection = sourceLimitQuery as CollectionResourceQueryable <TSource>; if (collection == null) { throw new InvalidOperationException("This object is not a supported collection resource."); } return(collection.Size); }