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

Information
Class: ZhEaIsNsAaBn.Infrastructure.Core.DbContextProvider<T>
Assembly: ZhEaIsNsAaBn.Infrastructure.Core
File(s): /home/runner/work/ZhEaIsNsAaBn.Libraries.V1/ZhEaIsNsAaBn.Libraries.V1/src/DataBasePackages/ZhEaIsNsAaBn.Infrastructure.Core/DbContexts/DbContextProvider.cs
Line coverage
83%
Covered lines: 41
Uncovered lines: 8
Coverable lines: 49
Total lines: 148
Line coverage: 83.6%
Branch coverage
71%
Covered branches: 20
Total branches: 28
Branch coverage: 71.4%
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%
GetDbContext(...)50%20627.27%
GetDbContextAsync()100%66100%
Dispose()100%11100%
DisposeAsync()100%66100%
Dispose(...)37.5%88100%
RequireFactory()100%22100%

File(s)

/home/runner/work/ZhEaIsNsAaBn.Libraries.V1/ZhEaIsNsAaBn.Libraries.V1/src/DataBasePackages/ZhEaIsNsAaBn.Infrastructure.Core/DbContexts/DbContextProvider.cs

#LineLine coverage
 1namespace ZhEaIsNsAaBn.Infrastructure.Core;
 2
 3/// <summary>
 4/// Default <see cref="IDbContextProvider{TDbContext}"/>. Wraps the context DI gives it (scoped registration), or create
 5/// contexts from an <see cref="IDbContextFactory{TContext}"/> (pooled registration).
 6/// </summary>
 7/// <remarks>
 8/// The shared context is created once per provider. A shared context the provider created from the factory is disposed
 9/// with the provider (for a pool this returns it to the pool); a context DI gave it is left to DI.
 10/// </remarks>
 11/// <typeparam name="TDbContext">The application's context.</typeparam>
 12public class DbContextProvider< TDbContext > : IDbContextProvider<TDbContext>, IDisposable, IAsyncDisposable
 13    where TDbContext : DbContext
 14{
 15    private readonly IDbContextFactory<TDbContext>? _dbContextFactory;
 33616    private readonly SemaphoreSlim                  _getDbContextLock = new( 1, 1 );
 17    private          TDbContext?                    _dbContext;
 18    private          bool                           _ownsDbContext;
 19    private          bool                           _disposed;
 20
 21
 22    /// <summary>Creates a provider that always hands out <paramref name="dbContext"/> as the shared context.</summary>
 23    /// <param name="dbContext">The context from DI.</param>
 24    /// <param name="dbContextFactory">Optional factory for <c>singleInstance: false</c>; without one, asking for a new 
 25    /// <exception cref="ArgumentNullException"><paramref name="dbContext"/> is <see langword="null"/>.</exception>
 29626    public DbContextProvider( TDbContext dbContext, IDbContextFactory<TDbContext>? dbContextFactory = null )
 27    {
 29628        ArgumentNullException.ThrowIfNull( dbContext );
 29
 29630        _dbContext        = dbContext;
 29631        _dbContextFactory = dbContextFactory;
 29632    }
 33
 34    /// <summary>Creates a provider that takes every context from <paramref name="dbContextFactory"/>.</summary>
 35    /// <param name="dbContextFactory">The factory, e.g. from <c>AddPooledDbContextFactory</c>.</param>
 36    /// <exception cref="ArgumentNullException"><paramref name="dbContextFactory"/> is <see langword="null"/>.</exceptio
 4037    public DbContextProvider( IDbContextFactory<TDbContext> dbContextFactory )
 38    {
 4039        ArgumentNullException.ThrowIfNull( dbContextFactory );
 40
 4041        _dbContextFactory = dbContextFactory;
 4042    }
 43
 44
 45    /// <inheritdoc />
 46    public virtual TDbContext GetDbContext( bool singleInstance = true, CancellationToken cancellationToken = default )
 47    {
 30048        ObjectDisposedException.ThrowIf( _disposed, this );
 49
 30450        if ( !singleInstance ) { return RequireFactory().CreateDbContext(); }
 51
 52
 59253        if ( _dbContext is not null ) { return _dbContext; }
 54
 55
 056        var factory = RequireFactory();
 57
 58
 059        _getDbContextLock.Wait( cancellationToken );
 60
 61        try
 62        {
 063            if ( _dbContext is null )
 64            {
 065                _dbContext     = factory.CreateDbContext();
 066                _ownsDbContext = true;
 67            }
 68
 69
 070            return _dbContext;
 71        }
 072        finally { _getDbContextLock.Release(); }
 073    }
 74
 75    /// <inheritdoc />
 76    public virtual async Task<TDbContext> GetDbContextAsync( bool singleInstance = true, CancellationToken cancellationT
 77    {
 31678        ObjectDisposedException.ThrowIf( _disposed, this );
 79
 33280        if ( !singleInstance ) { return await RequireFactory().CreateDbContextAsync( cancellationToken ).ConfigureAwait(
 81
 82
 56883        if ( _dbContext is not null ) { return _dbContext; }
 84
 85
 3286        var factory = RequireFactory();
 87
 88
 3289        await _getDbContextLock.WaitAsync( cancellationToken ).ConfigureAwait( false );
 90
 91        try
 92        {
 2893            if ( _dbContext is null )
 94            {
 2495                _dbContext     = await factory.CreateDbContextAsync( cancellationToken ).ConfigureAwait( false );
 2496                _ownsDbContext = true;
 97            }
 98
 99
 28100            return _dbContext;
 101        }
 28102        finally { _getDbContextLock.Release(); }
 312103    }
 104
 105    /// <summary>Disposes the shared context if this provider created it.</summary>
 106    public void Dispose()
 107    {
 24108        Dispose( true );
 24109        GC.SuppressFinalize( this );
 24110    }
 111
 112    /// <summary>Async version of <see cref="Dispose()"/>.</summary>
 113    /// <returns>A task that completes when the shared context is disposed.</returns>
 114    public async ValueTask DisposeAsync()
 115    {
 76116        if ( !_disposed && _ownsDbContext && _dbContext is not null ) { await _dbContext.DisposeAsync().ConfigureAwait( 
 117
 118
 56119        _ownsDbContext = false;
 56120        Dispose( true );
 56121        GC.SuppressFinalize( this );
 56122    }
 123
 124    /// <summary>Releases the provider's resources.</summary>
 125    /// <param name="disposing"><see langword="true"/> when called from <see cref="Dispose()"/>.</param>
 126    protected virtual void Dispose( bool disposing )
 127    {
 80128        if ( _disposed ) { return; }
 129
 130
 80131        if ( disposing )
 132        {
 80133            if ( _ownsDbContext ) { _dbContext?.Dispose(); }
 134
 135
 80136            _getDbContextLock.Dispose();
 137        }
 138
 139
 80140        _dbContext = null;
 80141        _disposed  = true;
 80142    }
 143
 144
 145    private IDbContextFactory<TDbContext> RequireFactory()
 52146        => _dbContextFactory ??
 52147           throw new InvalidOperationException( $"No IDbContextFactory<{typeof( TDbContext ).Name}> is registered. Regis
 148}