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

Information
Class: ZhEaIsNsAaBn.Infrastructure.Core.BaseDbContextConfiguration
Assembly: ZhEaIsNsAaBn.Infrastructure.Core
File(s): /home/runner/work/ZhEaIsNsAaBn.Libraries.V1/ZhEaIsNsAaBn.Libraries.V1/src/DataBasePackages/ZhEaIsNsAaBn.Infrastructure.Core/DbContexts/BaseDbContextConfiguration.cs
Line coverage
98%
Covered lines: 59
Uncovered lines: 1
Coverable lines: 60
Total lines: 139
Line coverage: 98.3%
Branch coverage
87%
Covered branches: 28
Total branches: 32
Branch coverage: 87.5%
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.Core/DbContexts/BaseDbContextConfiguration.cs

#LineLine coverage
 1using System.Reflection;
 2using Microsoft.EntityFrameworkCore.Metadata;
 3using PhoneNumbers;
 4
 5namespace ZhEaIsNsAaBn.Infrastructure.Core;
 6
 7/// <summary>
 8/// Model conventions shared by <see cref="BaseDbContext{TAppDbContext}"/> and the Identity variants. Provider-neutral: 
 9/// Unicode and precision are facets; default-value SQL comes from the context's <see cref="IModelDefaultsProvider"/>.
 10/// </summary>
 11internal static class BaseDbContextConfiguration
 12{
 13    private const int EnumLength  = 50;
 14    private const int ULongLength = 20;
 15
 16
 17    internal static void OnModelCreating( ModelBuilder modelBuilder, Action<ModelBuilder> customConfiguration, Assembly 
 18    {
 4419        ConfigureBaseEntityDefaults( modelBuilder, defaults?.CreatedDateDefaultSql );
 4420        ConfigureDecimalProperties( modelBuilder );
 4421        ConfigureDeleteBehaviors( modelBuilder );
 22
 4423        customConfiguration( modelBuilder );
 4424        modelBuilder.ApplyConfigurationsFromAssembly( configurationAssembly );
 25
 4426        ConfigureOwnershipDeleteBehaviors( modelBuilder );
 4427        ConfigurePhoneNumberProperties( modelBuilder );
 4428        ConfigureStatus( modelBuilder );
 4429        ConfigureGuidId( modelBuilder, defaults?.GuidKeyDefaultSql );
 4430    }
 31
 32    internal static void ConfigureEnumsProperties( ModelBuilder modelBuilder )
 33    {
 6434        foreach ( var property in modelBuilder.Model.GetEntityTypes().SelectMany( t => t.GetProperties() ).Where( p => p
 35        {
 36            // Stored as the enum name: Unicode text of 50 (nvarchar(50) on SQL Server).
 1637            property.SetProviderClrType( typeof( string ) );
 1638            property.SetMaxLength( EnumLength );
 1639            property.SetIsUnicode( true );
 40        }
 1641    }
 42
 43    internal static void ConfigureUlongProperties( ModelBuilder modelBuilder )
 44    {
 9645        foreach ( var property in modelBuilder.Model.GetEntityTypes()
 1646                                              .SelectMany( t => t.GetProperties() )
 1647                                              .Where( p => p.ClrType == typeof( ulong ) || p.ClrType == typeof( ulong? )
 48        {
 3249            property.SetMaxLength( ULongLength );
 3250            property.SetIsUnicode( true );
 3251            property.SetValueConverter( new ULongStringConverter() );
 52        }
 1653    }
 54
 55    private static void ConfigurePhoneNumberProperties( ModelBuilder modelBuilder )
 56    {
 8857        foreach ( var property in modelBuilder.Model.GetEntityTypes()
 4458                                              .SelectMany( t => t.GetProperties() )
 4459                                              .Where( p => p.ClrType == typeof( PhoneNumber ) ) )
 60        {
 061            property.SetValueConverter( property.IsNullable ? typeof( NullablePhoneNumberConverter ) : typeof( PhoneNumb
 62        }
 63
 64
 4465        modelBuilder.Ignore<PhoneNumber>();
 4466    }
 67
 68    private static void ConfigureBaseEntityDefaults( ModelBuilder modelBuilder, string? createdDateDefaultSql )
 69    {
 43270        foreach ( var entity in modelBuilder.Model.GetEntityTypes() )
 71        {
 17272            if ( entity.FindProperty( nameof( IBaseTrackableEntity.CreatedDate ) ) is { } createdDate )
 73            {
 9674                createdDate.IsNullable = false;
 75
 76                // The database fills it only when the provider supplies the SQL; otherwise the app sets it.
 9677                if ( createdDateDefaultSql is null ) { continue; }
 78
 79
 7680                createdDate.ValueGenerated = ValueGenerated.OnAdd;
 7681                createdDate.SetDefaultValueSql( createdDateDefaultSql );
 82            }
 83        }
 4484    }
 85
 86    private static void ConfigureDecimalProperties( ModelBuilder modelBuilder )
 87    {
 16088        foreach ( var property in modelBuilder.Model.GetEntityTypes()
 4489                                              .SelectMany( t => t.GetProperties() )
 4490                                              .Where( p => p.ClrType == typeof( decimal ) || p.ClrType == typeof( decima
 91        {
 3692            property.SetPrecision( 18 );
 3693            property.SetScale( 2 );
 94        }
 4495    }
 96
 97    private static void ConfigureDeleteBehaviors( ModelBuilder modelBuilder )
 98    {
 29699        foreach ( var foreignKey in modelBuilder.Model.GetEntityTypes().SelectMany( e => e.GetForeignKeys() ) )
 100        {
 104101            foreignKey.DeleteBehavior = DeleteBehavior.Restrict;
 102        }
 44103    }
 104
 105    /// An owned entity goes with its owner: a Restrict ownership makes <c>Remove( owner )</c> throw. ClientCascade dele
 106    /// entries and keeps the database foreign key at NO ACTION, so the schema (and the migration diff) doesn't change.
 107    private static void ConfigureOwnershipDeleteBehaviors( ModelBuilder modelBuilder )
 108    {
 112109        foreach ( var foreignKey in modelBuilder.Model.GetEntityTypes()
 44110                                                .SelectMany( e => e.GetForeignKeys() )
 44111                                                .Where( k => k.IsOwnership && k.DeleteBehavior == DeleteBehavior.Restric
 112        {
 12113            foreignKey.DeleteBehavior = DeleteBehavior.ClientCascade;
 114        }
 44115    }
 116
 117    private static void ConfigureGuidId( ModelBuilder modelBuilder, string? guidKeyDefaultSql )
 118    {
 56119        if ( guidKeyDefaultSql is null ) { return; }
 120
 121
 80122        foreach ( var property in modelBuilder.Model.GetEntityTypes()
 32123                                              .Select( e => e.FindPrimaryKey() )
 32124                                              .OfType<IMutableKey>()
 32125                                              .SelectMany( k => k.Properties )
 32126                                              .Where( p => p.ClrType == typeof( Guid ) ) )
 127        {
 8128            property.SetDefaultValueSql( guidKeyDefaultSql );
 129        }
 32130    }
 131
 132    private static void ConfigureStatus( ModelBuilder modelBuilder )
 133    {
 504134        foreach ( var entity in modelBuilder.Model.GetEntityTypes() )
 135        {
 208136            entity.FindProperty( nameof( IStatusEntity.StatusUser ) )?.SetMaxLength( 50 );
 137        }
 44138    }
 139}