< Summary

Information
Class: ProjectTemplate.Infrastructure.Data.Extensions.InfrastructureDataAccessServiceExtensions
Assembly: ProjectTemplate.Infrastructure
File(s): /home/runner/work/NetCoreApplicationTemplate/NetCoreApplicationTemplate/src/ProjectTemplate.Infrastructure/Data/Extensions/InfrastructureDataAccessServiceExtensions.cs
Line coverage
100%
Covered lines: 74
Uncovered lines: 0
Coverable lines: 74
Total lines: 158
Line coverage: 100%
Branch coverage
86%
Covered branches: 26
Total branches: 30
Branch coverage: 86.6%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
AddApplicationInfrastructureDataAccess(...)100%66100%
ResolveDataAccessRegistration(...)80%2020100%
ConfigureProvider(...)100%44100%
get_Provider()100%11100%
get_ConnectionString()100%11100%
get_AuditStorageMode()100%11100%
get_IsDisabled()100%11100%
Enabled(...)100%11100%
Disabled(...)100%11100%

File(s)

/home/runner/work/NetCoreApplicationTemplate/NetCoreApplicationTemplate/src/ProjectTemplate.Infrastructure/Data/Extensions/InfrastructureDataAccessServiceExtensions.cs

#LineLine coverage
 1using Microsoft.EntityFrameworkCore;
 2using Microsoft.Extensions.Configuration;
 3using Microsoft.Extensions.DependencyInjection;
 4using Microsoft.Extensions.DependencyInjection.Extensions;
 5using ProjectTemplate.Infrastructure.Data.Auditing;
 6using ProjectTemplate.Infrastructure.Data.ExternalLogins;
 7using ProjectTemplate.Infrastructure.Data.Options;
 8
 9namespace ProjectTemplate.Infrastructure.Data.Extensions;
 10
 11/// <summary>
 12/// Provides infrastructure-owned service registration methods for application data access.
 13/// </summary>
 14public static class InfrastructureDataAccessServiceExtensions
 15{
 16    /// <summary>
 17    /// Registers EF Core data access services for infrastructure and non-web consumers.
 18    /// </summary>
 19    public static IServiceCollection AddApplicationInfrastructureDataAccess(
 20        this IServiceCollection services,
 21        IConfiguration configuration)
 22    {
 21223        ArgumentNullException.ThrowIfNull(services);
 21224        ArgumentNullException.ThrowIfNull(configuration);
 25
 21226        services
 21227            .AddOptions<DataAccessOptions>()
 21228            .Bind(configuration.GetSection(DataAccessOptions.SectionName))
 28629            .Validate(options => !string.IsNullOrWhiteSpace(options.Provider),
 21230                "ProjectTemplate:DataAccess:Provider must not be empty.")
 28631            .Validate(options => DataAccessOptions.IsDisabledProvider(options.Provider)
 28632                || !string.IsNullOrWhiteSpace(options.ConnectionStringName),
 21233                "ProjectTemplate:DataAccess:ConnectionStringName must not be empty when data access is enabled.")
 28634            .Validate(options => AuditStorageModes.IsSupported(options.Auditing.StorageMode),
 21235                "ProjectTemplate:DataAccess:Auditing:StorageMode must be Local, Outbox, or ExternalSink.")
 21236            .ValidateOnStart();
 37
 21238        DataAccessRegistration registration = ResolveDataAccessRegistration(configuration);
 20039        if (registration.IsDisabled)
 40        {
 1241            return services;
 42        }
 43
 18844        services.TryAddScoped<ICurrentActorAccessor, SystemCurrentActorAccessor>();
 18845        services.TryAddScoped<IApplicationAuditContextAccessor, SystemApplicationAuditContextAccessor>();
 18846        services.TryAddScoped<IApplicationAuditValuePolicy, DefaultApplicationAuditValuePolicy>();
 18847        services.TryAddSingleton<IApplicationMutationManifestBuilder, CanonicalApplicationMutationManifestBuilder>();
 18848        services.TryAddSingleton<IApplicationMutationManifestHasher, Sha256ApplicationMutationManifestHasher>();
 18849        services.TryAddSingleton<IApplicationMutationManifestVerifier, ApplicationMutationManifestVerifier>();
 50
 18851        if (AuditStorageModes.IsLocal(registration.AuditStorageMode))
 52        {
 18653            services.TryAddScoped<IApplicationAuditStore, LocalApplicationAuditStore>();
 54        }
 55
 18856        services.TryAddScoped<ContextIsolatedApplicationSaveChangesPipeline>();
 18857        services.TryAddScoped<IApplicationSaveChangesPipeline>(serviceProvider =>
 20458            serviceProvider.GetRequiredService<ContextIsolatedApplicationSaveChangesPipeline>());
 18859        services.TryAddScoped<IApplicationMutationAuditReceiptRegistry>(serviceProvider =>
 19260            serviceProvider.GetRequiredService<ContextIsolatedApplicationSaveChangesPipeline>());
 18861        services.TryAddScoped<IApplicationMutationAuditReceiptAccessor, ApplicationDbContextMutationAuditReceiptAccessor
 18862        services.TryAddScoped<ApplicationSaveChangesInterceptor>();
 63
 20664        services.AddDbContext<ApplicationDbContext>(options => ConfigureProvider(
 20665                options,
 20666                registration.Provider,
 20667                registration.ConnectionString));
 68
 18869        services.AddDbContextFactory<ApplicationDbContext>(
 1670            options => ConfigureProvider(
 1671                    options,
 1672                    registration.Provider,
 1673                    registration.ConnectionString),
 18874            ServiceLifetime.Scoped);
 75
 18876        services.TryAddScoped<IExternalLoginAccountResolver, EfCoreExternalLoginAccountResolver>();
 18877        return services;
 78    }
 79
 80    private static DataAccessRegistration ResolveDataAccessRegistration(IConfiguration configuration)
 81    {
 21282        DataAccessOptions dataAccessOptions = configuration
 21283            .GetSection(DataAccessOptions.SectionName)
 21284            .Get<DataAccessOptions>() ?? new DataAccessOptions();
 85
 21286        string provider = dataAccessOptions.Provider?.Trim() ?? string.Empty;
 21287        string connectionStringName = dataAccessOptions.ConnectionStringName?.Trim() ?? string.Empty;
 21288        string auditStorageMode = AuditStorageModes.Normalize(dataAccessOptions.Auditing.StorageMode);
 89
 21290        if (string.IsNullOrWhiteSpace(provider))
 91        {
 492            throw new InvalidOperationException("Application data access provider was not configured.");
 93        }
 94
 20895        if (!AuditStorageModes.IsSupported(auditStorageMode))
 96        {
 297            throw new InvalidOperationException("Application audit storage mode was not configured with a supported valu
 98        }
 99
 206100        if (DataAccessOptions.IsDisabledProvider(provider))
 101        {
 12102            return DataAccessRegistration.Disabled(provider, auditStorageMode);
 103        }
 104
 194105        if (string.IsNullOrWhiteSpace(connectionStringName))
 106        {
 4107            throw new InvalidOperationException("Application data access connection string name was not configured.");
 108        }
 109
 190110        string connectionString = configuration.GetConnectionString(connectionStringName)
 190111            ?? throw new InvalidOperationException($"Connection string '{connectionStringName}' was not configured.");
 112
 188113        return DataAccessRegistration.Enabled(provider, connectionString, auditStorageMode);
 114    }
 115
 116    private static void ConfigureProvider(
 117        DbContextOptionsBuilder options,
 118        string provider,
 119        string connectionString)
 120    {
 34121        if (provider.Equals(DataAccessOptions.SqliteProvider, StringComparison.OrdinalIgnoreCase))
 122        {
 20123            options.UseSqlite(connectionString);
 20124            return;
 125        }
 126
 14127        if (provider.Equals(DataAccessOptions.SqlServerProvider, StringComparison.OrdinalIgnoreCase))
 128        {
 12129            options.UseSqlServer(connectionString);
 12130            return;
 131        }
 132
 2133        throw new InvalidOperationException(
 2134            $"Unsupported data access provider '{provider}'. Supported providers: {DataAccessOptions.SqliteProvider}, {D
 135    }
 136
 137    private readonly record struct DataAccessRegistration(
 34138        string Provider,
 34139        string ConnectionString,
 188140        string AuditStorageMode,
 200141        bool IsDisabled)
 142    {
 143        public static DataAccessRegistration Enabled(
 144            string provider,
 145            string connectionString,
 146            string auditStorageMode)
 147        {
 188148            return new(provider, connectionString, auditStorageMode, false);
 149        }
 150
 151        public static DataAccessRegistration Disabled(
 152            string provider,
 153            string auditStorageMode)
 154        {
 12155            return new(provider, string.Empty, auditStorageMode, true);
 156        }
 157    }
 158}