< Summary - ZhEaIsNsAaBn.Libraries coverage (affected: 23 packages)

Information
Class: ZhEaIsNsAaBn.Infrastructure.Specifications.SpecificationExtensions
Assembly: ZhEaIsNsAaBn.Infrastructure.Specifications
File(s): /home/runner/work/ZhEaIsNsAaBn.Libraries.V1/ZhEaIsNsAaBn.Libraries.V1/src/DataBasePackages/ZhEaIsNsAaBn.Infrastructure.Specifications/Extensions/SpecificationExtensions.cs
Line coverage
40%
Covered lines: 32
Uncovered lines: 48
Coverable lines: 80
Total lines: 447
Line coverage: 40%
Branch coverage
22%
Covered branches: 8
Total branches: 36
Branch coverage: 22.2%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/ZhEaIsNsAaBn.Libraries.V1/ZhEaIsNsAaBn.Libraries.V1/src/DataBasePackages/ZhEaIsNsAaBn.Infrastructure.Specifications/Extensions/SpecificationExtensions.cs

#LineLine coverage
 1using Ardalis.Specification.EntityFrameworkCore;
 2
 3namespace ZhEaIsNsAaBn.Infrastructure.Specifications;
 4
 5/// <summary>
 6/// Runs a <see cref="BaseSpecification{TEntity}"/> against an <see cref="IQueryable{T}"/> with Ardalis' default evaluat
 7/// specification returns its <see cref="BaseSpecification{TEntity}.IsValid"/> failure without querying; build, translat
 8/// errors come back as an <see cref="Error"/> (cancellation still throws). Only <c>StreamList*Async</c> can throw, whil
 9/// A query doesn't expose its <c>DbContext</c>, so database errors here are <see cref="Error.Unknown"/>; the repository
 10/// </summary>
 11public static class SpecificationExtensions
 12{
 13    /// <summary>Whether any row matches <paramref name="specification"/> (criteria only).</summary>
 14    /// <typeparam name="TEntity">The entity type.</typeparam>
 15    /// <param name="query">The source, e.g. <c>dbContext.Set&lt;TEntity&gt;()</c>.</param>
 16    /// <param name="specification">The specification.</param>
 17    /// <param name="cancellationToken">Token to cancel the query.</param>
 18    /// <returns><see langword="true"/> when a row matches; the specification's failure; or the classified error.</retur
 19    public static async Task<LayerResponse<bool>> AnyAsync< TEntity >( this IQueryable<TEntity> query, BaseSpecification
 20        where TEntity : class
 21    {
 022        ArgumentNullException.ThrowIfNull( specification );
 23
 024        if ( specification.IsValid.IsFailure ) { return LayerResponse<bool>.Failure( specification.IsValid.Errors ); }
 25
 26
 027        return await RunAsync( Filter( query, specification, true ), q => EntityFrameworkQueryableExtensions.AnyAsync( q
 028    }
 29
 30    /// <summary>Applies <paramref name="specification"/> to <paramref name="query"/>.</summary>
 31    /// <typeparam name="TEntity">The entity type.</typeparam>
 32    /// <param name="query">The source.</param>
 33    /// <param name="specification">The specification.</param>
 34    /// <param name="evaluateCriteriaOnly"><see langword="true"/> to apply only the criteria (no order, paging or includ
 35    /// <param name="specificationEvaluator">The evaluator; Ardalis' default when <see langword="null"/>.</param>
 36    /// <param name="cancellationToken">Not used; kept for callers.</param>
 37    /// <returns>The filtered query, or <see langword="null"/> when the specification is invalid.</returns>
 38    public static Task<IQueryable<TEntity>?> ApplySpecificationAsync< TEntity >(
 39            this IQueryable<TEntity> query, BaseSpecification<TEntity> specification, bool evaluateCriteriaOnly = false,
 40            CancellationToken cancellationToken = default
 41        )
 42        where TEntity : class
 43    {
 044        ArgumentNullException.ThrowIfNull( specification );
 45
 046        specificationEvaluator ??= SpecificationEvaluator.Default;
 47
 48
 049        return Task.FromResult( specification.IsValid.IsSuccess ? specificationEvaluator.GetQuery( query, specification,
 50    }
 51
 52    /// <summary>Counts the rows matching <paramref name="specification"/> (criteria only).</summary>
 53    /// <typeparam name="TEntity">The entity type.</typeparam>
 54    /// <param name="query">The source.</param>
 55    /// <param name="specification">The specification.</param>
 56    /// <param name="cancellationToken">Token to cancel the query.</param>
 57    /// <returns>The count; the specification's failure; or the classified error.</returns>
 58    public static async Task<LayerResponse<int>> CountAsync< TEntity >( this IQueryable<TEntity> query, BaseSpecificatio
 59        where TEntity : class
 60    {
 061        ArgumentNullException.ThrowIfNull( specification );
 62
 063        if ( specification.IsValid.IsFailure ) { return LayerResponse<int>.Failure( specification.IsValid.Errors ); }
 64
 65
 066        return await RunAsync( Filter( query, specification, true ), q => EntityFrameworkQueryableExtensions.CountAsync(
 067    }
 68
 69    /// <summary>Counts all rows of <paramref name="query"/>.</summary>
 70    /// <typeparam name="TEntity">The entity type.</typeparam>
 71    /// <param name="query">The source.</param>
 72    /// <param name="cancellationToken">Token to cancel the query.</param>
 73    /// <returns>The count, or the classified database error.</returns>
 74    public static Task<LayerResponse<int>> CountAsync< TEntity >( this IQueryable<TEntity> query, CancellationToken canc
 75        where TEntity : class
 476        => SafeExecution.ExecuteSafeAsync( () => EntityFrameworkQueryableExtensions.CountAsync( query, cancellationToken
 77
 78    /// <summary>The first row matching <paramref name="specification"/>, or <see langword="null"/>.</summary>
 79    /// <typeparam name="TEntity">The entity type.</typeparam>
 80    /// <param name="query">The source.</param>
 81    /// <param name="specification">The specification.</param>
 82    /// <param name="cancellationToken">Token to cancel the query.</param>
 83    /// <returns>The row; the specification's failure; or the classified error.</returns>
 84    public static async Task<LayerResponse<TEntity>> FirstOrDefaultAsync< TEntity >( this IQueryable<TEntity> query, Sin
 85        where TEntity : class
 86    {
 087        ArgumentNullException.ThrowIfNull( specification );
 88
 089        if ( specification.IsValid.IsFailure ) { return LayerResponse<TEntity>.Failure( specification.IsValid.Errors ); 
 90
 91
 092        return await FirstAsync( Filter( query, specification ), cancellationToken ).ConfigureAwait( false );
 093    }
 94
 95    /// <summary>The rows matching <paramref name="specification"/>, read in full.</summary>
 96    /// <typeparam name="TEntity">The entity type.</typeparam>
 97    /// <param name="query">The source.</param>
 98    /// <param name="specification">The specification.</param>
 99    /// <param name="cancellationToken">Token to cancel the query.</param>
 100    /// <returns>The rows; the specification's failure; or the classified error (also for errors while reading).</return
 101    public static async Task<LayerResponse<IReadOnlyList<TEntity>>> GetListAsync< TEntity >( this IQueryable<TEntity> qu
 102        where TEntity : class
 103    {
 4104        ArgumentNullException.ThrowIfNull( specification );
 105
 4106        if ( specification.IsValid.IsFailure ) { return LayerResponse<IReadOnlyList<TEntity>>.Failure( specification.IsV
 107
 108
 4109        return await ListAsync( Filter( query, specification ), cancellationToken ).ConfigureAwait( false );
 4110    }
 111
 112    /// <summary>One page of rows matching <paramref name="specification"/>, read in full.</summary>
 113    /// <typeparam name="TEntity">The entity type.</typeparam>
 114    /// <param name="query">The source.</param>
 115    /// <param name="specification">The page specification.</param>
 116    /// <param name="cancellationToken">Token to cancel the query.</param>
 117    /// <returns>The rows; the specification's failure; or the classified error.</returns>
 118    public static Task<LayerResponse<IReadOnlyList<TEntity>>> GetListPaginationAsync< TEntity >(
 119            this IQueryable<TEntity> query, PaginationSpecification<TEntity> specification, CancellationToken cancellati
 120        )
 121        where TEntity : class
 0122        => query.GetListAsync( specification, cancellationToken );
 123
 124    /// <summary>The last row matching <paramref name="specification"/> (it must order the rows), or <see langword="null
 125    /// <typeparam name="TEntity">The entity type.</typeparam>
 126    /// <param name="query">The source.</param>
 127    /// <param name="specification">The specification.</param>
 128    /// <param name="cancellationToken">Token to cancel the query.</param>
 129    /// <returns>The row; the specification's failure; or the classified error.</returns>
 130    public static async Task<LayerResponse<TEntity>> LastOrDefaultAsync< TEntity >( this IQueryable<TEntity> query, Sing
 131        where TEntity : class
 132    {
 4133        ArgumentNullException.ThrowIfNull( specification );
 134
 4135        if ( specification.IsValid.IsFailure ) { return LayerResponse<TEntity>.Failure( specification.IsValid.Errors ); 
 136
 137
 4138        return await LastAsync( Filter( query, specification ), cancellationToken ).ConfigureAwait( false );
 4139    }
 140
 141    /// <summary>
 142    /// The rows matching <paramref name="specification"/> as a lazy stream. Nothing runs until you enumerate, and error
 143    /// enumerating (database, translation) <b>throw</b>; use <see cref="GetListAsync{TEntity}"/> to get them as an <see
 144    /// </summary>
 145    /// <typeparam name="TEntity">The entity type.</typeparam>
 146    /// <param name="query">The source.</param>
 147    /// <param name="specification">The specification.</param>
 148    /// <param name="cancellationToken">Not used; pass it to the enumeration (<c>WithCancellation</c>).</param>
 149    /// <returns>The stream; the specification's failure; or the error building the query.</returns>
 150    public static Task<LayerResponse<IAsyncEnumerable<TEntity>>> StreamListAsync< TEntity >( this IQueryable<TEntity> qu
 151        where TEntity : class
 152    {
 4153        ArgumentNullException.ThrowIfNull( specification );
 154
 4155        return Task.FromResult( specification.IsValid.IsFailure
 4156                                    ? LayerResponse<IAsyncEnumerable<TEntity>>.Failure( specification.IsValid.Errors )
 4157                                    : Lazily( Filter( query, specification ) ) );
 158    }
 159
 160    /// <summary>One page as a lazy stream; see <see cref="StreamListAsync{TEntity}"/> (enumeration can throw).</summary
 161    /// <typeparam name="TEntity">The entity type.</typeparam>
 162    /// <param name="query">The source.</param>
 163    /// <param name="specification">The page specification.</param>
 164    /// <param name="cancellationToken">Not used; pass it to the enumeration.</param>
 165    /// <returns>The stream; the specification's failure; or the error building the query.</returns>
 166    public static Task<LayerResponse<IAsyncEnumerable<TEntity>>> StreamListPaginationAsync< TEntity >(
 167            this IQueryable<TEntity> query, PaginationSpecification<TEntity> specification, CancellationToken cancellati
 168        )
 169        where TEntity : class
 0170        => query.StreamListAsync( specification, cancellationToken );
 171
 172
 173    // ---- Projections (a): Specification<TEntity, TResult> with Query.Select ----
 174
 175    /// <summary>The first row matching <paramref name="specification"/>, projected by its <c>Query.Select</c>, or <see 
 176    /// <typeparam name="TEntity">The entity type.</typeparam>
 177    /// <typeparam name="TResult">The read model.</typeparam>
 178    /// <param name="query">The source.</param>
 179    /// <param name="specification">The specification; it must call <c>Query.Select</c>.</param>
 180    /// <param name="cancellationToken">Token to cancel the query.</param>
 181    /// <returns>The row; the specification's failure; or the classified error.</returns>
 182    public static async Task<LayerResponse<TResult>> FirstOrDefaultAsync< TEntity, TResult >(
 183            this IQueryable<TEntity> query, SingleSpecification<TEntity, TResult> specification, CancellationToken cance
 184        )
 185        where TEntity : class
 186    {
 0187        ArgumentNullException.ThrowIfNull( specification );
 188
 0189        if ( specification.IsValid.IsFailure ) { return LayerResponse<TResult>.Failure( specification.IsValid.Errors ); 
 190
 191
 0192        return await FirstAsync( Project( query, specification ), cancellationToken ).ConfigureAwait( false );
 0193    }
 194
 195    /// <summary>The rows matching <paramref name="specification"/>, projected by its <c>Query.Select</c>, read in full.
 196    /// <typeparam name="TEntity">The entity type.</typeparam>
 197    /// <typeparam name="TResult">The read model.</typeparam>
 198    /// <param name="query">The source.</param>
 199    /// <param name="specification">The specification; it must call <c>Query.Select</c>.</param>
 200    /// <param name="cancellationToken">Token to cancel the query.</param>
 201    /// <returns>The rows; the specification's failure; or the classified error.</returns>
 202    public static async Task<LayerResponse<IReadOnlyList<TResult>>> GetListAsync< TEntity, TResult >(
 203            this IQueryable<TEntity> query, BaseSpecification<TEntity, TResult> specification, CancellationToken cancell
 204        )
 205        where TEntity : class
 206    {
 8207        ArgumentNullException.ThrowIfNull( specification );
 208
 8209        if ( specification.IsValid.IsFailure ) { return LayerResponse<IReadOnlyList<TResult>>.Failure( specification.IsV
 210
 211
 8212        return await ListAsync( Project( query, specification ), cancellationToken ).ConfigureAwait( false );
 8213    }
 214
 215    /// <summary>One page of rows matching <paramref name="specification"/>, projected by its <c>Query.Select</c>, read 
 216    /// <typeparam name="TEntity">The entity type.</typeparam>
 217    /// <typeparam name="TResult">The read model.</typeparam>
 218    /// <param name="query">The source.</param>
 219    /// <param name="specification">The page specification; it must call <c>Query.Select</c>.</param>
 220    /// <param name="cancellationToken">Token to cancel the query.</param>
 221    /// <returns>The rows; the specification's failure; or the classified error.</returns>
 222    public static Task<LayerResponse<IReadOnlyList<TResult>>> GetListPaginationAsync< TEntity, TResult >(
 223            this IQueryable<TEntity> query, PaginationSpecification<TEntity, TResult> specification, CancellationToken c
 224        )
 225        where TEntity : class
 0226        => query.GetListAsync<TEntity, TResult>( specification, cancellationToken );
 227
 228    /// <summary>The last row matching <paramref name="specification"/> (it must order the rows), projected by its <c>Qu
 229    /// <typeparam name="TEntity">The entity type.</typeparam>
 230    /// <typeparam name="TResult">The read model.</typeparam>
 231    /// <param name="query">The source.</param>
 232    /// <param name="specification">The specification; it must call <c>Query.Select</c>.</param>
 233    /// <param name="cancellationToken">Token to cancel the query.</param>
 234    /// <returns>The row; the specification's failure; or the classified error.</returns>
 235    public static async Task<LayerResponse<TResult>> LastOrDefaultAsync< TEntity, TResult >(
 236            this IQueryable<TEntity> query, SingleSpecification<TEntity, TResult> specification, CancellationToken cance
 237        )
 238        where TEntity : class
 239    {
 0240        ArgumentNullException.ThrowIfNull( specification );
 241
 0242        if ( specification.IsValid.IsFailure ) { return LayerResponse<TResult>.Failure( specification.IsValid.Errors ); 
 243
 244
 0245        return await LastAsync( Project( query, specification ), cancellationToken ).ConfigureAwait( false );
 0246    }
 247
 248    /// <summary>The rows matching <paramref name="specification"/>, projected by its <c>Query.Select</c>, as a lazy str
 249    /// <typeparam name="TEntity">The entity type.</typeparam>
 250    /// <typeparam name="TResult">The read model.</typeparam>
 251    /// <param name="query">The source.</param>
 252    /// <param name="specification">The specification; it must call <c>Query.Select</c>.</param>
 253    /// <param name="cancellationToken">Not used; pass it to the enumeration.</param>
 254    /// <returns>The stream; the specification's failure; or the error building the query.</returns>
 255    public static Task<LayerResponse<IAsyncEnumerable<TResult>>> StreamListAsync< TEntity, TResult >(
 256            this IQueryable<TEntity> query, BaseSpecification<TEntity, TResult> specification, CancellationToken cancell
 257        )
 258        where TEntity : class
 259    {
 0260        ArgumentNullException.ThrowIfNull( specification );
 261
 0262        return Task.FromResult( specification.IsValid.IsFailure
 0263                                    ? LayerResponse<IAsyncEnumerable<TResult>>.Failure( specification.IsValid.Errors )
 0264                                    : Lazily( Project( query, specification ) ) );
 265    }
 266
 267    /// <summary>One projected page as a lazy stream (enumeration can throw).</summary>
 268    /// <typeparam name="TEntity">The entity type.</typeparam>
 269    /// <typeparam name="TResult">The read model.</typeparam>
 270    /// <param name="query">The source.</param>
 271    /// <param name="specification">The page specification; it must call <c>Query.Select</c>.</param>
 272    /// <param name="cancellationToken">Not used; pass it to the enumeration.</param>
 273    /// <returns>The stream; the specification's failure; or the error building the query.</returns>
 274    public static Task<LayerResponse<IAsyncEnumerable<TResult>>> StreamListPaginationAsync< TEntity, TResult >(
 275            this IQueryable<TEntity> query, PaginationSpecification<TEntity, TResult> specification, CancellationToken c
 276        )
 277        where TEntity : class
 0278        => query.StreamListAsync<TEntity, TResult>( specification, cancellationToken );
 279
 280
 281    // ---- Projections (b): Func<IQueryable<TEntity>, IQueryable<TResult>>, e.g. a Mapperly IQueryable projection ----
 282
 283    /// <summary>The first row matching <paramref name="specification"/>, projected by <paramref name="project"/>, or <s
 284    /// <typeparam name="TEntity">The entity type.</typeparam>
 285    /// <typeparam name="TResult">The read model.</typeparam>
 286    /// <param name="query">The source.</param>
 287    /// <param name="specification">The specification.</param>
 288    /// <param name="project">Turns the filtered query into the read model, e.g. <c>q =&gt; q.ProjectToSummary()</c> (Ma
 289    /// <param name="cancellationToken">Token to cancel the query.</param>
 290    /// <returns>The row; the specification's failure; or the classified error.</returns>
 291    public static async Task<LayerResponse<TResult>> FirstOrDefaultAsync< TEntity, TResult >(
 292            this IQueryable<TEntity> query, SingleSpecification<TEntity> specification, Func<IQueryable<TEntity>, IQuery
 293            CancellationToken cancellationToken = default
 294        )
 295        where TEntity : class
 296    {
 8297        ArgumentNullException.ThrowIfNull( specification );
 8298        ArgumentNullException.ThrowIfNull( project );
 299
 8300        if ( specification.IsValid.IsFailure ) { return LayerResponse<TResult>.Failure( specification.IsValid.Errors ); 
 301
 302
 8303        return await FirstAsync( Project( query, specification, project ), cancellationToken ).ConfigureAwait( false );
 8304    }
 305
 306    /// <summary>The rows matching <paramref name="specification"/>, projected by <paramref name="project"/>, read in fu
 307    /// <typeparam name="TEntity">The entity type.</typeparam>
 308    /// <typeparam name="TResult">The read model.</typeparam>
 309    /// <param name="query">The source.</param>
 310    /// <param name="specification">The specification.</param>
 311    /// <param name="project">Turns the filtered query into the read model.</param>
 312    /// <param name="cancellationToken">Token to cancel the query.</param>
 313    /// <returns>The rows; the specification's failure; or the classified error.</returns>
 314    public static async Task<LayerResponse<IReadOnlyList<TResult>>> GetListAsync< TEntity, TResult >(
 315            this IQueryable<TEntity> query, BaseSpecification<TEntity> specification, Func<IQueryable<TEntity>, IQueryab
 316            CancellationToken cancellationToken = default
 317        )
 318        where TEntity : class
 319    {
 0320        ArgumentNullException.ThrowIfNull( specification );
 0321        ArgumentNullException.ThrowIfNull( project );
 322
 0323        if ( specification.IsValid.IsFailure ) { return LayerResponse<IReadOnlyList<TResult>>.Failure( specification.IsV
 324
 325
 0326        return await ListAsync( Project( query, specification, project ), cancellationToken ).ConfigureAwait( false );
 0327    }
 328
 329    /// <summary>One page of rows matching <paramref name="specification"/>, projected by <paramref name="project"/>, re
 330    /// <typeparam name="TEntity">The entity type.</typeparam>
 331    /// <typeparam name="TResult">The read model.</typeparam>
 332    /// <param name="query">The source.</param>
 333    /// <param name="specification">The page specification.</param>
 334    /// <param name="project">Turns the page query into the read model.</param>
 335    /// <param name="cancellationToken">Token to cancel the query.</param>
 336    /// <returns>The rows; the specification's failure; or the classified error.</returns>
 337    public static Task<LayerResponse<IReadOnlyList<TResult>>> GetListPaginationAsync< TEntity, TResult >(
 338            this IQueryable<TEntity> query, PaginationSpecification<TEntity> specification, Func<IQueryable<TEntity>, IQ
 339            CancellationToken cancellationToken = default
 340        )
 341        where TEntity : class
 0342        => query.GetListAsync( specification, project, cancellationToken );
 343
 344    /// <summary>The last row matching <paramref name="specification"/> (it must order the rows), projected by <paramref
 345    /// <typeparam name="TEntity">The entity type.</typeparam>
 346    /// <typeparam name="TResult">The read model.</typeparam>
 347    /// <param name="query">The source.</param>
 348    /// <param name="specification">The specification.</param>
 349    /// <param name="project">Turns the filtered query into the read model.</param>
 350    /// <param name="cancellationToken">Token to cancel the query.</param>
 351    /// <returns>The row; the specification's failure; or the classified error.</returns>
 352    public static async Task<LayerResponse<TResult>> LastOrDefaultAsync< TEntity, TResult >(
 353            this IQueryable<TEntity> query, SingleSpecification<TEntity> specification, Func<IQueryable<TEntity>, IQuery
 354            CancellationToken cancellationToken = default
 355        )
 356        where TEntity : class
 357    {
 0358        ArgumentNullException.ThrowIfNull( specification );
 0359        ArgumentNullException.ThrowIfNull( project );
 360
 0361        if ( specification.IsValid.IsFailure ) { return LayerResponse<TResult>.Failure( specification.IsValid.Errors ); 
 362
 363
 0364        return await LastAsync( Project( query, specification, project ), cancellationToken ).ConfigureAwait( false );
 0365    }
 366
 367    /// <summary>The rows matching <paramref name="specification"/>, projected by <paramref name="project"/>, as a lazy 
 368    /// <typeparam name="TEntity">The entity type.</typeparam>
 369    /// <typeparam name="TResult">The read model.</typeparam>
 370    /// <param name="query">The source.</param>
 371    /// <param name="specification">The specification.</param>
 372    /// <param name="project">Turns the filtered query into the read model.</param>
 373    /// <param name="cancellationToken">Not used; pass it to the enumeration.</param>
 374    /// <returns>The stream; the specification's failure; or the error building the query.</returns>
 375    public static Task<LayerResponse<IAsyncEnumerable<TResult>>> StreamListAsync< TEntity, TResult >(
 376            this IQueryable<TEntity> query, BaseSpecification<TEntity> specification, Func<IQueryable<TEntity>, IQueryab
 377            CancellationToken cancellationToken = default
 378        )
 379        where TEntity : class
 380    {
 0381        ArgumentNullException.ThrowIfNull( specification );
 0382        ArgumentNullException.ThrowIfNull( project );
 383
 0384        return Task.FromResult( specification.IsValid.IsFailure
 0385                                    ? LayerResponse<IAsyncEnumerable<TResult>>.Failure( specification.IsValid.Errors )
 0386                                    : Lazily( Project( query, specification, project ) ) );
 387    }
 388
 389    /// <summary>One page projected by <paramref name="project"/>, as a lazy stream (enumeration can throw).</summary>
 390    /// <typeparam name="TEntity">The entity type.</typeparam>
 391    /// <typeparam name="TResult">The read model.</typeparam>
 392    /// <param name="query">The source.</param>
 393    /// <param name="specification">The page specification.</param>
 394    /// <param name="project">Turns the page query into the read model.</param>
 395    /// <param name="cancellationToken">Not used; pass it to the enumeration.</param>
 396    /// <returns>The stream; the specification's failure; or the error building the query.</returns>
 397    public static Task<LayerResponse<IAsyncEnumerable<TResult>>> StreamListPaginationAsync< TEntity, TResult >(
 398            this IQueryable<TEntity> query, PaginationSpecification<TEntity> specification, Func<IQueryable<TEntity>, IQ
 399            CancellationToken cancellationToken = default
 400        )
 401        where TEntity : class
 0402        => query.StreamListAsync( specification, project, cancellationToken );
 403
 404
 405    // Known issue #4 fixed: a failure building the query (no Query.Select, a throwing projector) is returned as an Erro
 406    private static LayerResponse<IQueryable<TResult>> Project< TEntity, TResult >( IQueryable<TEntity> query, ISpecifica
 407        where TEntity : class
 8408        => SafeExecution.ExecuteSafe( () => SpecificationEvaluator.Default.GetQuery( query, specification ) );
 409
 410    private static LayerResponse<IQueryable<TResult>> Project< TEntity, TResult >(
 411            IQueryable<TEntity> query, ISpecification<TEntity> specification, Func<IQueryable<TEntity>, IQueryable<TResu
 412        )
 413        where TEntity : class
 8414        => SafeExecution.ExecuteSafe( () => project( SpecificationEvaluator.Default.GetQuery( query, specification ) ) )
 415
 416    private static LayerResponse<IQueryable<TEntity>> Filter< TEntity >( IQueryable<TEntity> query, ISpecification<TEnti
 417        where TEntity : class
 12418        => SafeExecution.ExecuteSafe( () => SpecificationEvaluator.Default.GetQuery( query, specification, evaluateCrite
 419
 420
 421    // ---- Shared by the extensions and SpecificationRepository ----
 422
 423    /// Runs the query through the SafeExecution ladder: database and translation errors come back as an Error (cancella
 424    /// The IQueryable extensions have no context, so provider errors become Error.Unknown; the repository passes its co
 425    /// Only a bare DbSet exposes its services; a filtered EntityQueryable hides the context behind private EF fields (n
 426    /// so recovering it is not reliable (README → Errors).
 427    internal static async Task<LayerResponse<T>> RunAsync< TSource, T >(
 428            LayerResponse<IQueryable<TSource>> query, Func<IQueryable<TSource>, Task<T>> execute, IDbErrorClassifier? cl
 429        )
 156430        => query.IsFailure ? LayerResponse<T>.Failure( query.Errors ) : await SafeExecution.ExecuteSafeAsync( () => exec
 431
 432    internal static Task<LayerResponse<TResult>> FirstAsync< TResult >( LayerResponse<IQueryable<TResult>> query, Cancel
 44433        => RunAsync<TResult, TResult>( query, q => EntityFrameworkQueryableExtensions.FirstOrDefaultAsync( q, cancellati
 434
 435    internal static Task<LayerResponse<TResult>> LastAsync< TResult >( LayerResponse<IQueryable<TResult>> query, Cancell
 32436        => RunAsync<TResult, TResult>( query, q => EntityFrameworkQueryableExtensions.LastOrDefaultAsync( q, cancellatio
 437
 438    internal static Task<LayerResponse<IReadOnlyList<TResult>>> ListAsync< TResult >(
 439            LayerResponse<IQueryable<TResult>> query, CancellationToken cancellationToken, IDbErrorClassifier? classifie
 440        )
 64441        => RunAsync<TResult, IReadOnlyList<TResult>>( query, async q => await EntityFrameworkQueryableExtensions.ToListA
 442
 443    internal static LayerResponse<IAsyncEnumerable<TResult>> Lazily< TResult >( LayerResponse<IQueryable<TResult>> query
 28444        => query.IsFailure
 28445               ? LayerResponse<IAsyncEnumerable<TResult>>.Failure( query.Errors )
 28446               : LayerResponse<IAsyncEnumerable<TResult>>.Success( query.Result!.AsAsyncEnumerable() );
 447}

Methods/Properties

AnyAsync()
ApplySpecificationAsync(System.Linq.IQueryable`1<TEntity>,ZhEaIsNsAaBn.Infrastructure.Specifications.BaseSpecification`1<TEntity>,System.Boolean,Ardalis.Specification.EntityFrameworkCore.SpecificationEvaluator,System.Threading.CancellationToken)
CountAsync()
CountAsync(System.Linq.IQueryable`1<TEntity>,System.Threading.CancellationToken)
FirstOrDefaultAsync()
GetListAsync()
GetListPaginationAsync(System.Linq.IQueryable`1<TEntity>,ZhEaIsNsAaBn.Infrastructure.Specifications.PaginationSpecification`1<TEntity>,System.Threading.CancellationToken)
LastOrDefaultAsync()
StreamListAsync(System.Linq.IQueryable`1<TEntity>,ZhEaIsNsAaBn.Infrastructure.Specifications.BaseSpecification`1<TEntity>,System.Threading.CancellationToken)
StreamListPaginationAsync(System.Linq.IQueryable`1<TEntity>,ZhEaIsNsAaBn.Infrastructure.Specifications.PaginationSpecification`1<TEntity>,System.Threading.CancellationToken)
FirstOrDefaultAsync()
GetListAsync()
GetListPaginationAsync(System.Linq.IQueryable`1<TEntity>,ZhEaIsNsAaBn.Infrastructure.Specifications.PaginationSpecification`2<TEntity,TResult>,System.Threading.CancellationToken)
LastOrDefaultAsync()
StreamListAsync(System.Linq.IQueryable`1<TEntity>,ZhEaIsNsAaBn.Infrastructure.Specifications.BaseSpecification`2<TEntity,TResult>,System.Threading.CancellationToken)
StreamListPaginationAsync(System.Linq.IQueryable`1<TEntity>,ZhEaIsNsAaBn.Infrastructure.Specifications.PaginationSpecification`2<TEntity,TResult>,System.Threading.CancellationToken)
FirstOrDefaultAsync()
GetListAsync()
GetListPaginationAsync(System.Linq.IQueryable`1<TEntity>,ZhEaIsNsAaBn.Infrastructure.Specifications.PaginationSpecification`1<TEntity>,System.Func`2<System.Linq.IQueryable`1<TEntity>,System.Linq.IQueryable`1<TResult>>,System.Threading.CancellationToken)
LastOrDefaultAsync()
StreamListAsync(System.Linq.IQueryable`1<TEntity>,ZhEaIsNsAaBn.Infrastructure.Specifications.BaseSpecification`1<TEntity>,System.Func`2<System.Linq.IQueryable`1<TEntity>,System.Linq.IQueryable`1<TResult>>,System.Threading.CancellationToken)
StreamListPaginationAsync(System.Linq.IQueryable`1<TEntity>,ZhEaIsNsAaBn.Infrastructure.Specifications.PaginationSpecification`1<TEntity>,System.Func`2<System.Linq.IQueryable`1<TEntity>,System.Linq.IQueryable`1<TResult>>,System.Threading.CancellationToken)
Project(System.Linq.IQueryable`1<TEntity>,Ardalis.Specification.ISpecification`2<TEntity,TResult>)
Project(System.Linq.IQueryable`1<TEntity>,Ardalis.Specification.ISpecification`1<TEntity>,System.Func`2<System.Linq.IQueryable`1<TEntity>,System.Linq.IQueryable`1<TResult>>)
Filter(System.Linq.IQueryable`1<TEntity>,Ardalis.Specification.ISpecification`1<TEntity>,System.Boolean)
RunAsync()
FirstAsync(ZhEaIsNsAaBn.Utilities.LayerResponse`1<System.Linq.IQueryable`1<TResult>>,System.Threading.CancellationToken,ZhEaIsNsAaBn.Infrastructure.Core.IDbErrorClassifier)
LastAsync(ZhEaIsNsAaBn.Utilities.LayerResponse`1<System.Linq.IQueryable`1<TResult>>,System.Threading.CancellationToken,ZhEaIsNsAaBn.Infrastructure.Core.IDbErrorClassifier)
ListAsync(ZhEaIsNsAaBn.Utilities.LayerResponse`1<System.Linq.IQueryable`1<TResult>>,System.Threading.CancellationToken,ZhEaIsNsAaBn.Infrastructure.Core.IDbErrorClassifier)
Lazily(ZhEaIsNsAaBn.Utilities.LayerResponse`1<System.Linq.IQueryable`1<TResult>>)