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

Information
Class: ZhEaIsNsAaBn.Infrastructure.Specifications.SpecificationRepository<T1, T2>
Assembly: ZhEaIsNsAaBn.Infrastructure.Specifications
File(s): /home/runner/work/ZhEaIsNsAaBn.Libraries.V1/ZhEaIsNsAaBn.Libraries.V1/src/DataBasePackages/ZhEaIsNsAaBn.Infrastructure.Specifications/Repositories/SpecificationRepository.cs
Line coverage
100%
Covered lines: 2
Uncovered lines: 0
Coverable lines: 2
Total lines: 287
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
.ctor(...)100%11100%

File(s)

/home/runner/work/ZhEaIsNsAaBn.Libraries.V1/ZhEaIsNsAaBn.Libraries.V1/src/DataBasePackages/ZhEaIsNsAaBn.Infrastructure.Specifications/Repositories/SpecificationRepository.cs

#LineLine coverage
 1namespace ZhEaIsNsAaBn.Infrastructure.Specifications;
 2
 3/// <summary><see cref="SpecificationRepository{TDbContext, TEntity, TId}"/> for <see cref="int"/>-keyed entities.</summ
 4/// <typeparam name="TDbContext">The application's context.</typeparam>
 5/// <typeparam name="TEntity">The entity type.</typeparam>
 6public class SpecificationRepository< TDbContext, TEntity > : SpecificationRepository<TDbContext, TEntity, int>, ISpecif
 7    where TEntity : class, IBaseEntity
 8    where TDbContext : DbContext
 9{
 10    /// <inheritdoc />
 29611    public SpecificationRepository( IDbContextProvider<TDbContext> dbContextProvider ) : base( dbContextProvider ) { }
 12
 13    /// <inheritdoc />
 9614    public SpecificationRepository( IDbContextProvider<TDbContext> dbContextProvider, ISpecificationEvaluator specificat
 15}
 16
 17/// <summary>The ready-made <see cref="ISpecificationRepository{TEntity, TId}"/> over the provider's shared context.</su
 18/// <typeparam name="TDbContext">The application's context.</typeparam>
 19/// <typeparam name="TEntity">The entity type.</typeparam>
 20/// <typeparam name="TId">The key type.</typeparam>
 21public class SpecificationRepository< TDbContext, TEntity, TId > : BaseSpecificationRepository<TDbContext, TEntity, TId>
 22    where TEntity : class, IBaseEntity<TId>
 23    where TDbContext : DbContext
 24    where TId : struct, IEquatable<TId>
 25{
 26    /// <summary>Creates the repository.</summary>
 27    /// <param name="dbContextProvider">The context provider.</param>
 28    public SpecificationRepository( IDbContextProvider<TDbContext> dbContextProvider ) : base( dbContextProvider ) { }
 29
 30    /// <summary>Creates the repository.</summary>
 31    /// <param name="dbContextProvider">The context provider.</param>
 32    /// <param name="specificationEvaluator">The specification evaluator.</param>
 33    public SpecificationRepository( IDbContextProvider<TDbContext> dbContextProvider, ISpecificationEvaluator specificat
 34
 35
 36    /// <inheritdoc />
 37    public virtual LayerResponse<TId> AddAndSave( TEntity entity, CancellationToken cancellationToken = default ) => bas
 38
 39    /// <inheritdoc />
 40    public virtual ValueTask<LayerResponse<TId>> AddAndSaveAsync( TEntity entity, CancellationToken cancellationToken = 
 41
 42    /// <inheritdoc />
 43    public virtual Task<LayerResponse<int>> AddRangeAndSaveAsync( IEnumerable<TEntity> entities, CancellationToken cance
 44
 45    /// <inheritdoc />
 46    public async Task<LayerResponse<bool>> AnyAsync( BaseSpecification<TEntity> specification, CancellationToken cancell
 47        => await SpecificationExtensions.RunAsync( await QueryAsync( specification, true, cancellationToken ).ConfigureA
 48                                        .ConfigureAwait( false );
 49
 50    /// <inheritdoc />
 51    public async Task<LayerResponse<int>> CountAsync( BaseSpecification<TEntity> specification, CancellationToken cancel
 52        => await SpecificationExtensions.RunAsync( await QueryAsync( specification, true, cancellationToken ).ConfigureA
 53                                        .ConfigureAwait( false );
 54
 55    /// <inheritdoc />
 56    public async Task<LayerResponse<int>> CountAsync( CancellationToken cancellationToken = default )
 57    {
 58        var context = await GetDbContextAsync( cancellationToken ).ConfigureAwait( false );
 59
 60
 61        return await SafeExecution.ExecuteSafeAsync( () => EntityFrameworkQueryableExtensions.CountAsync( context.Set<TE
 62                                  .ConfigureAwait( false );
 63    }
 64
 65    /// <inheritdoc />
 66    public virtual LayerResponse<int> DeleteAndSave( TEntity entity, CancellationToken cancellationToken = default ) => 
 67
 68    /// <inheritdoc />
 69    public async Task<LayerResponse<TEntity>> FirstOrDefaultAsync( SingleSpecification<TEntity> specification, Cancellat
 70        => await SpecificationExtensions.FirstAsync( await QueryAsync( specification, false, cancellationToken ).Configu
 71
 72    /// <inheritdoc />
 73    public async Task<LayerResponse<IReadOnlyList<TEntity>>> GetListAsync( BaseSpecification<TEntity> specification, Can
 74        => await SpecificationExtensions.ListAsync( await QueryAsync( specification, false, cancellationToken ).Configur
 75
 76    /// <inheritdoc />
 77    public Task<LayerResponse<IReadOnlyList<TEntity>>> GetListPaginationAsync( PaginationSpecification<TEntity> specific
 78        => GetListAsync( specification, cancellationToken );
 79
 80    /// <inheritdoc />
 81    public async Task<LayerResponse<IAsyncEnumerable<TEntity>>> StreamListAsync( BaseSpecification<TEntity> specificatio
 82        => SpecificationExtensions.Lazily( await QueryAsync( specification, false, cancellationToken ).ConfigureAwait( f
 83
 84    /// <inheritdoc />
 85    public Task<LayerResponse<IAsyncEnumerable<TEntity>>> StreamListPaginationAsync( PaginationSpecification<TEntity> sp
 86        => StreamListAsync( specification, cancellationToken );
 87
 88    /// <inheritdoc />
 89    public async Task<LayerResponse<TEntity>> LastOrDefaultAsync( SingleSpecification<TEntity> specification, Cancellati
 90        => await SpecificationExtensions.LastAsync( await QueryAsync( specification, false, cancellationToken ).Configur
 91
 92    /// <inheritdoc />
 93    public async Task<LayerResponse<TResult>> FirstOrDefaultAsync< TResult >( SingleSpecification<TEntity, TResult> spec
 94        => await SpecificationExtensions.FirstAsync( await ApplySpecificationAsync( specification, cancellationToken ).C
 95
 96    /// <inheritdoc />
 97    public async Task<LayerResponse<TResult>> FirstOrDefaultAsync< TResult >(
 98            SingleSpecification<TEntity> specification, Func<IQueryable<TEntity>, IQueryable<TResult>> project, Cancella
 99        )
 100        => await SpecificationExtensions.FirstAsync( await ApplySpecificationAsync( specification, project, cancellation
 101
 102    /// <inheritdoc />
 103    public async Task<LayerResponse<IReadOnlyList<TResult>>> GetListAsync< TResult >( BaseSpecification<TEntity, TResult
 104        => await SpecificationExtensions.ListAsync( await ApplySpecificationAsync( specification, cancellationToken ).Co
 105
 106    /// <inheritdoc />
 107    public async Task<LayerResponse<IReadOnlyList<TResult>>> GetListAsync< TResult >(
 108            BaseSpecification<TEntity> specification, Func<IQueryable<TEntity>, IQueryable<TResult>> project, Cancellati
 109        )
 110        => await SpecificationExtensions.ListAsync( await ApplySpecificationAsync( specification, project, cancellationT
 111
 112    /// <inheritdoc />
 113    public Task<LayerResponse<IReadOnlyList<TResult>>> GetListPaginationAsync< TResult >( PaginationSpecification<TEntit
 114        => GetListAsync<TResult>( specification, cancellationToken );
 115
 116    /// <inheritdoc />
 117    public Task<LayerResponse<IReadOnlyList<TResult>>> GetListPaginationAsync< TResult >(
 118            PaginationSpecification<TEntity> specification, Func<IQueryable<TEntity>, IQueryable<TResult>> project, Canc
 119        )
 120        => GetListAsync( specification, project, cancellationToken );
 121
 122    /// <inheritdoc />
 123    public async Task<LayerResponse<IAsyncEnumerable<TResult>>> StreamListAsync< TResult >( BaseSpecification<TEntity, T
 124        => SpecificationExtensions.Lazily( await ApplySpecificationAsync( specification, cancellationToken ).ConfigureAw
 125
 126    /// <inheritdoc />
 127    public async Task<LayerResponse<IAsyncEnumerable<TResult>>> StreamListAsync< TResult >(
 128            BaseSpecification<TEntity> specification, Func<IQueryable<TEntity>, IQueryable<TResult>> project, Cancellati
 129        )
 130        => SpecificationExtensions.Lazily( await ApplySpecificationAsync( specification, project, cancellationToken ).Co
 131
 132    /// <inheritdoc />
 133    public Task<LayerResponse<IAsyncEnumerable<TResult>>> StreamListPaginationAsync< TResult >( PaginationSpecification<
 134        => StreamListAsync<TResult>( specification, cancellationToken );
 135
 136    /// <inheritdoc />
 137    public Task<LayerResponse<IAsyncEnumerable<TResult>>> StreamListPaginationAsync< TResult >(
 138            PaginationSpecification<TEntity> specification, Func<IQueryable<TEntity>, IQueryable<TResult>> project, Canc
 139        )
 140        => StreamListAsync( specification, project, cancellationToken );
 141
 142    /// <inheritdoc />
 143    public async Task<LayerResponse<TResult>> LastOrDefaultAsync< TResult >( SingleSpecification<TEntity, TResult> speci
 144        => await SpecificationExtensions.LastAsync( await ApplySpecificationAsync( specification, cancellationToken ).Co
 145
 146    /// <inheritdoc />
 147    public async Task<LayerResponse<TResult>> LastOrDefaultAsync< TResult >(
 148            SingleSpecification<TEntity> specification, Func<IQueryable<TEntity>, IQueryable<TResult>> project, Cancella
 149        )
 150        => await SpecificationExtensions.LastAsync( await ApplySpecificationAsync( specification, project, cancellationT
 151
 152    // ---- Sync twins ----
 153
 154    /// <inheritdoc />
 155    public LayerResponse<bool> Any( BaseSpecification<TEntity> specification, CancellationToken cancellationToken = defa
 156        => Read( specification, true, q => q.Any(), cancellationToken );
 157
 158    /// <inheritdoc />
 159    public LayerResponse<int> Count( BaseSpecification<TEntity> specification, CancellationToken cancellationToken = def
 160        => Read( specification, true, q => q.Count(), cancellationToken );
 161
 162    /// <inheritdoc />
 163    public LayerResponse<int> Count( CancellationToken cancellationToken = default )
 164    {
 165        var context = GetDbContext( cancellationToken );
 166
 167
 168        return SafeExecution.ExecuteSafe( () => context.Set<TEntity>().Count(), context.GetDbErrorClassifier() );
 169    }
 170
 171    /// <inheritdoc />
 172    public LayerResponse<TEntity> FirstOrDefault( SingleSpecification<TEntity> specification, CancellationToken cancella
 173        => Read( specification, false, q => q.FirstOrDefault()!, cancellationToken );
 174
 175    /// <inheritdoc />
 176    public LayerResponse<TResult> FirstOrDefault< TResult >( SingleSpecification<TEntity, TResult> specification, Cancel
 177        => Read( specification, q => q.FirstOrDefault()!, cancellationToken );
 178
 179    /// <inheritdoc />
 180    public LayerResponse<TResult> FirstOrDefault< TResult >(
 181            SingleSpecification<TEntity> specification, Func<IQueryable<TEntity>, IQueryable<TResult>> project, Cancella
 182        )
 183    {
 184        ArgumentNullException.ThrowIfNull( project );
 185
 186        return Read( specification, false, q => project( q ).FirstOrDefault()!, cancellationToken );
 187    }
 188
 189    /// <inheritdoc />
 190    public LayerResponse<IReadOnlyList<TEntity>> GetList( BaseSpecification<TEntity> specification, CancellationToken ca
 191        => Read<IReadOnlyList<TEntity>>( specification, false, q => q.ToList(), cancellationToken );
 192
 193    /// <inheritdoc />
 194    public LayerResponse<IReadOnlyList<TResult>> GetList< TResult >( BaseSpecification<TEntity, TResult> specification, 
 195        => Read<TResult, IReadOnlyList<TResult>>( specification, q => q.ToList(), cancellationToken );
 196
 197    /// <inheritdoc />
 198    public LayerResponse<IReadOnlyList<TResult>> GetList< TResult >(
 199            BaseSpecification<TEntity> specification, Func<IQueryable<TEntity>, IQueryable<TResult>> project, Cancellati
 200        )
 201    {
 202        ArgumentNullException.ThrowIfNull( project );
 203
 204        return Read<IReadOnlyList<TResult>>( specification, false, q => project( q ).ToList(), cancellationToken );
 205    }
 206
 207    /// <inheritdoc />
 208    public LayerResponse<IReadOnlyList<TEntity>> GetListPagination( PaginationSpecification<TEntity> specification, Canc
 209        => GetList( specification, cancellationToken );
 210
 211    /// <inheritdoc />
 212    public LayerResponse<IReadOnlyList<TResult>> GetListPagination< TResult >( PaginationSpecification<TEntity, TResult>
 213        => GetList<TResult>( specification, cancellationToken );
 214
 215    /// <inheritdoc />
 216    public LayerResponse<IReadOnlyList<TResult>> GetListPagination< TResult >(
 217            PaginationSpecification<TEntity> specification, Func<IQueryable<TEntity>, IQueryable<TResult>> project, Canc
 218        )
 219        => GetList( specification, project, cancellationToken );
 220
 221    /// <inheritdoc />
 222    public LayerResponse<TEntity> LastOrDefault( SingleSpecification<TEntity> specification, CancellationToken cancellat
 223        => Read( specification, false, q => q.LastOrDefault()!, cancellationToken );
 224
 225    /// <inheritdoc />
 226    public LayerResponse<TResult> LastOrDefault< TResult >( SingleSpecification<TEntity, TResult> specification, Cancell
 227        => Read( specification, q => q.LastOrDefault()!, cancellationToken );
 228
 229    /// <inheritdoc />
 230    public LayerResponse<TResult> LastOrDefault< TResult >(
 231            SingleSpecification<TEntity> specification, Func<IQueryable<TEntity>, IQueryable<TResult>> project, Cancella
 232        )
 233    {
 234        ArgumentNullException.ThrowIfNull( project );
 235
 236        return Read( specification, false, q => project( q ).LastOrDefault()!, cancellationToken );
 237    }
 238
 239    /// <inheritdoc />
 240    public virtual LayerResponse<int> UpdateAndSave( TEntity entity, CancellationToken cancellationToken = default ) => 
 241
 242    /// <inheritdoc />
 243    public virtual LayerResponse<int> UpdateRangeAndSave( IEnumerable<TEntity> entities, CancellationToken cancellationT
 244
 245
 246    // Validates the specification and builds the query with the injected evaluator; a build failure comes back as an Er
 247    private async Task<LayerResponse<IQueryable<TEntity>>> QueryAsync( BaseSpecification<TEntity> specification, bool ev
 248    {
 249        ArgumentNullException.ThrowIfNull( specification );
 250
 251        if ( specification.IsValid.IsFailure ) { return LayerResponse<IQueryable<TEntity>>.Failure( specification.IsVali
 252
 253
 254        var context = await GetDbContextAsync( cancellationToken ).ConfigureAwait( false );
 255
 256
 257        return SafeExecution.ExecuteSafe( () => SpecificationEvaluator.GetQuery( context.Set<TEntity>().AsQueryable(), s
 258    }
 259
 260    // Validates, builds and runs a sync read inside the SafeExecution ladder, so build, translation and database errors
 261    private LayerResponse<T> Read< T >( BaseSpecification<TEntity> specification, bool evaluateCriteriaOnly, Func<IQuery
 262    {
 263        ArgumentNullException.ThrowIfNull( specification );
 264
 265        if ( specification.IsValid.IsFailure ) { return LayerResponse<T>.Failure( specification.IsValid.Errors ); }
 266
 267
 268        var context = GetDbContext( cancellationToken );
 269
 270
 271        return SafeExecution.ExecuteSafe( () => execute( SpecificationEvaluator.GetQuery( context.Set<TEntity>().AsQuery
 272                                          context.GetDbErrorClassifier() );
 273    }
 274
 275    private LayerResponse<T> Read< TResult, T >( BaseSpecification<TEntity, TResult> specification, Func<IQueryable<TRes
 276    {
 277        ArgumentNullException.ThrowIfNull( specification );
 278
 279        if ( specification.IsValid.IsFailure ) { return LayerResponse<T>.Failure( specification.IsValid.Errors ); }
 280
 281
 282        var context = GetDbContext( cancellationToken );
 283
 284
 285        return SafeExecution.ExecuteSafe( () => execute( SpecificationEvaluator.GetQuery( context.Set<TEntity>().AsQuery
 286    }
 287}