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

Information
Class: Microsoft.EntityFrameworkCore.SqlServerDbExceptionExtensions
Assembly: ZhEaIsNsAaBn.Infrastructure.SqlServer
File(s): /home/runner/work/ZhEaIsNsAaBn.Libraries.V1/ZhEaIsNsAaBn.Libraries.V1/src/DataBasePackages/ZhEaIsNsAaBn.Infrastructure.SqlServer/SqlServerDbExceptionExtensions.cs
Line coverage
62%
Covered lines: 36
Uncovered lines: 22
Coverable lines: 58
Total lines: 116
Line coverage: 62%
Branch coverage
28%
Covered branches: 28
Total branches: 98
Branch coverage: 28.5%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
Classify(...)46.42%532868.18%
Classify(...)10.34%6495844%
AddDatabaseAndUser(...)75%131281.81%

File(s)

/home/runner/work/ZhEaIsNsAaBn.Libraries.V1/ZhEaIsNsAaBn.Libraries.V1/src/DataBasePackages/ZhEaIsNsAaBn.Infrastructure.SqlServer/SqlServerDbExceptionExtensions.cs

#LineLine coverage
 1// ReSharper disable once CheckNamespace
 2namespace Microsoft.EntityFrameworkCore;
 3
 4/// <summary>
 5/// Turns SQL Server exceptions into an <see cref="Error"/> by error number. Additional data holds SQL details for logs 
 6/// (<see cref="Error.AdditionalData"/> is never serialized). No connection string, password or token is ever included.
 7/// </summary>
 8public static class SqlServerDbExceptionExtensions
 9{
 10    /// <summary>
 11    /// Classifies a failed save by the inner <see cref="SqlException"/> number. Additional data: <c>Number</c>, <c>Line
 12    /// <c>Message</c> (server message), <c>Procedure</c>; plus <c>Database</c> and <c>User</c> when <see cref="Exceptio
 13    /// <c>ConnectionString</c>. The connection string, password and tokens are never copied.
 14    /// </summary>
 15    /// <param name="exception">The exception.</param>
 16    /// <returns>
 17    /// One of <c>UniqueConstraintViolation</c>, <c>ConstraintViolation</c>, <c>RequiredFieldMissing</c>, <c>DataTooLong
 18    /// <c>NumericOverflow</c>, <c>InvalidDataType</c>, <c>Deadlock</c>, <c>Timeout</c>, <c>UnexpectedError</c>.
 19    /// </returns>
 20    /// <exception cref="ArgumentNullException"><paramref name="exception"/> is <see langword="null"/>.</exception>
 21    public static Error Classify( this DbUpdateException exception )
 22    {
 3923        ArgumentNullException.ThrowIfNull( exception );
 24
 3925        if ( exception.InnerException is not SqlException sqlException ) { return DbUpdateExceptions.UnexpectedError( ex
 26
 27
 3928        var additionalData = new Dictionary<string, object>
 3929                                 {
 3930                                     [ "Number" ]     = sqlException.Number,
 3931                                     [ "Message" ]    = sqlException.Message,
 3932                                     [ "Procedure" ]  = sqlException.Procedure,
 3933                                     [ "LineNumber" ] = sqlException.LineNumber
 3934                                 };
 35
 3936        AddDatabaseAndUser( additionalData, exception.Data[ "ConnectionString" ] as string );
 37
 38
 3939        return sqlException.Number switch
 3940                   {
 741                       2627 or 2601      => DbUpdateExceptions.UniqueConstraintViolation( exception, additionalData ),
 042                       547               => DbUpdateExceptions.ConstraintViolation( exception, additionalData ),
 043                       515               => DbUpdateExceptions.RequiredFieldMissing( exception, additionalData ),
 044                       8152              => DbUpdateExceptions.DataTooLong( exception, additionalData ),
 045                       8115              => DbUpdateExceptions.NumericOverflow( exception, additionalData ),
 046                       245 or 241 or 242 => DbUpdateExceptions.InvalidDataType( exception, additionalData ),
 047                       1205              => DbUpdateExceptions.Deadlock( exception, additionalData ),
 048                       -2                => DbUpdateExceptions.Timeout( exception, additionalData ),
 3249                       _                 => DbUpdateExceptions.UnexpectedError( exception, additionalData )
 3950                   };
 51    }
 52
 53    /// <summary>Classifies a <see cref="SqlException"/> by its number. Additional data: <c>Number</c>, <c>LineNumber</c
 54    /// <param name="exception">The exception.</param>
 55    /// <returns>An error from <see cref="SqlExceptions"/>; <c>Unknown</c> when the number isn't mapped.</returns>
 56    /// <exception cref="ArgumentNullException"><paramref name="exception"/> is <see langword="null"/>.</exception>
 57    public static Error Classify( this SqlException exception )
 58    {
 759        ArgumentNullException.ThrowIfNull( exception );
 60
 761        var additionalData = new Dictionary<string, object>
 762                                 {
 763                                     [ "Number" ]     = exception.Number,
 764                                     [ "LineNumber" ] = exception.LineNumber,
 765                                     [ "Procedure" ]  = exception.Procedure
 766                                 };
 67
 68
 769        return exception.Number switch
 770                   {
 071                       -1 or 2 or 1225 or 4060      => SqlExceptions.DatabaseNotAccessible( exception, additionalData ),
 072                       -2 or 8645 or 30053 or 1222  => SqlExceptions.RequestTimeout( exception, additionalData ),
 073                       18456                        => SqlExceptions.DataBaseAuthenticationFailed( exception, additional
 074                       241                          => SqlExceptions.InvalidData( exception, additionalData ),
 075                       512 or 511                   => SqlExceptions.TooManyRows( exception, additionalData ),
 476                       515                          => SqlExceptions.Null( exception, additionalData ),
 077                       1205                         => SqlExceptions.DeadlockVictim( exception, additionalData ),
 078                       2627 or 2601                 => SqlExceptions.UniqueConstraint( exception, additionalData ),
 079                       547                          => SqlExceptions.ForeignKey( exception, additionalData ),
 080                       8152                         => SqlExceptions.StringTooLong( exception, additionalData ),
 081                       8115                         => SqlExceptions.InvalidType( exception, additionalData ),
 382                       50000                        => SqlExceptions.CustomException( exception, additionalData ),
 083                       701 or 8651                  => SqlExceptions.OutOfMemory( exception, additionalData ),
 084                       1204                         => SqlExceptions.OutOfLocks( exception, additionalData ),
 085                       _                            => SqlExceptions.Unknown( exception, additionalData )
 786                   };
 87    }
 88
 89
 90    /// <summary>
 91    /// Adds <c>Database</c> (initial catalog) and <c>User</c> (user ID, else the authentication mode) from a connection
 92    /// The string itself, the password and any token are never stored; an unreadable string adds nothing.
 93    /// </summary>
 94    private static void AddDatabaseAndUser( Dictionary<string, object> additionalData, string? connectionString )
 95    {
 5096        if ( string.IsNullOrWhiteSpace( connectionString ) ) { return; }
 97
 98
 99        SqlConnectionStringBuilder builder;
 100
 56101        try { builder = new SqlConnectionStringBuilder( connectionString ); }
 0102        catch ( ArgumentException ) { return; }                       // malformed: nothing safe to extract
 0103        catch ( FormatException ) { return; }
 104
 105
 56106        if ( !string.IsNullOrWhiteSpace( builder.InitialCatalog ) ) { additionalData[ "Database" ] = builder.InitialCata
 107
 108
 28109        var user = !string.IsNullOrWhiteSpace( builder.UserID )                         ? builder.UserID
 28110                   : builder.Authentication != SqlAuthenticationMethod.NotSpecified ? builder.Authentication.ToString()
 28111                   : builder.IntegratedSecurity                                       ? "Integrated Security"
 28112                                                                                      : null;
 113
 56114        if ( user is not null ) { additionalData[ "User" ] = user; }
 28115    }
 116}