From e10b230d24eea034d5fe27fb799a2d6629b1d765 Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Fri, 21 Aug 2020 14:19:26 -0700 Subject: [PATCH] Fix | Perform Null check for SqlErrors in SqlException (#698) --- .../Microsoft.Data.SqlClient/SqlException.xml | 26 ++++-- .../src/Microsoft/Data/SqlClient/SqlError.cs | 83 +++++-------------- .../Microsoft/Data/SqlClient/SqlException.cs | 4 +- .../src/Microsoft/Data/SqlClient/SqlError.cs | 83 +++++++++---------- .../Microsoft/Data/SqlClient/SqlException.cs | 25 +++--- 5 files changed, 94 insertions(+), 127 deletions(-) diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlException.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlException.xml index 85604fde46..c5eafa53b1 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlException.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlException.xml @@ -85,7 +85,9 @@ catch (Exception ex) { For information about the warning and informational messages sent by SQL Server, see the Troubleshooting section of the SQL Server documentation. This is a wrapper for the property of the first in the property. - + + If is `null`, the [`default`](https://docs.microsoft.com/dotnet/csharp/language-reference/builtin-types/default-values) value for `byte` is returned. + ## Examples @@ -161,7 +163,9 @@ catch (Exception ex) { The line numbering starts at 1; if 0 is returned, the line number is not applicable. This is a wrapper for the property of the first in the property. - + + If is `null`, the [`default`](https://docs.microsoft.com/dotnet/csharp/language-reference/builtin-types/default-values) value for `int` is returned. + ## Examples @@ -190,7 +194,11 @@ catch (Exception ex) { property of the first in the property. For more information on SQL Server engine errors, see [Database Engine Events and Errors](/sql/relational-databases/errors-events/database-engine-events-and-errors). + This is a wrapper for the property of the first in the property. + + If is `null`, the [`default`](https://docs.microsoft.com/dotnet/csharp/language-reference/builtin-types/default-values) value for `int` is returned. + + For more information on SQL Server engine errors, see [Database Engine Events and Errors](/sql/relational-databases/errors-events/database-engine-events-and-errors). @@ -215,8 +223,9 @@ catch (Exception ex) { property of the first in the property. - + This is a wrapper for the property of the first in the property. + + If is `null`, the [`default`](https://docs.microsoft.com/dotnet/csharp/language-reference/builtin-types/default-values) value for `string` is returned. ## Examples @@ -241,7 +250,8 @@ catch (Exception ex) { ## Remarks This is a wrapper for the property of the first in the property. - + + If is `null`, the [`default`](https://docs.microsoft.com/dotnet/csharp/language-reference/builtin-types/default-values) value for `string` is returned. ## Examples @@ -266,7 +276,6 @@ catch (Exception ex) { ## Remarks This is a wrapper for the property of the first in the property. - ## Examples @@ -291,7 +300,8 @@ catch (Exception ex) { ## Remarks This is a wrapper for the property of the first in the property. - + + If is `null`, the [`default`](https://docs.microsoft.com/dotnet/csharp/language-reference/builtin-types/default-values) value for `byte` is returned. ## Examples diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlError.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlError.cs index 844f36312f..05c1dd75b5 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlError.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlError.cs @@ -9,34 +9,23 @@ namespace Microsoft.Data.SqlClient /// public sealed class SqlError { - private string _source = TdsEnums.SQL_PROVIDER_NAME; - private int _number; - private byte _state; - private byte _errorClass; - private string _server; - private string _message; - private string _procedure; - private int _lineNumber; - private int _win32ErrorCode; - private Exception _exception; - internal SqlError(int infoNumber, byte errorState, byte errorClass, string server, string errorMessage, string procedure, int lineNumber, uint win32ErrorCode, Exception exception = null) : this(infoNumber, errorState, errorClass, server, errorMessage, procedure, lineNumber, exception) { - _win32ErrorCode = (int)win32ErrorCode; + Win32ErrorCode = (int)win32ErrorCode; } internal SqlError(int infoNumber, byte errorState, byte errorClass, string server, string errorMessage, string procedure, int lineNumber, Exception exception = null) { - _number = infoNumber; - _state = errorState; - _errorClass = errorClass; - _server = server; - _message = errorMessage; - _procedure = procedure; - _lineNumber = lineNumber; - _win32ErrorCode = 0; - _exception = exception; + Number = infoNumber; + State = errorState; + Class = errorClass; + Server = server; + Message = errorMessage; + Procedure = procedure; + LineNumber = lineNumber; + Win32ErrorCode = 0; + Exception = exception; if (errorClass != 0) { SqlClientEventSource.Log.TraceEvent(" infoNumber={0}, errorState={1}, errorClass={2}, errorMessage='{3}', procedure='{4}', lineNumber={5}", infoNumber, (int)errorState, (int)errorClass, errorMessage, procedure ?? "None", (int)lineNumber); @@ -49,65 +38,35 @@ internal SqlError(int infoNumber, byte errorState, byte errorClass, string serve // way back to SqlException. If the user needs a call stack, they can obtain it on SqlException. public override string ToString() { - return typeof(SqlError).ToString() + ": " + _message; // since this is sealed so we can change GetType to typeof + return typeof(SqlError).ToString() + ": " + Message; // since this is sealed so we can change GetType to typeof } /// - public string Source - { - get { return _source; } - } + public string Source { get; private set; } = TdsEnums.SQL_PROVIDER_NAME; /// - public int Number - { - get { return _number; } - } + public int Number { get; private set; } /// - public byte State - { - get { return _state; } - } + public byte State { get; private set; } /// - public byte Class - { - get { return _errorClass; } - } + public byte Class { get; private set; } /// - public string Server - { - get { return _server; } - } + public string Server { get; private set; } /// - public string Message - { - get { return _message; } - } + public string Message { get; private set; } /// - public string Procedure - { - get { return _procedure; } - } + public string Procedure { get; private set; } /// - public int LineNumber - { - get { return _lineNumber; } - } + public int LineNumber { get; private set; } - internal int Win32ErrorCode - { - get { return _win32ErrorCode; } - } + internal int Win32ErrorCode { get; private set; } - internal Exception Exception - { - get { return _exception; } - } + internal Exception Exception { get; private set; } } } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlException.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlException.cs index b19798c52f..5f4e952ec8 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlException.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlException.cs @@ -89,7 +89,7 @@ public Guid ClientConnectionId /// public byte Class { - get { return Errors.Count > 0 ? this.Errors[0].Class : default; } + get { return Errors.Count > 0 ? Errors[0].Class : default; } } /// @@ -125,7 +125,7 @@ public byte State /// override public string Source { - get { return Errors.Count > 0 ? Errors[0].Source : default; } + get { return TdsEnums.SQL_PROVIDER_NAME; } } /// diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlError.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlError.cs index 10ac16d708..feec3a7438 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlError.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlError.cs @@ -6,109 +6,108 @@ namespace Microsoft.Data.SqlClient { - /// + /// [Serializable] public sealed class SqlError { - // bug fix - MDAC 48965 - missing source of exception - private string source = TdsEnums.SQL_PROVIDER_NAME; - private int number; - private byte state; - private byte errorClass; - [System.Runtime.Serialization.OptionalFieldAttribute(VersionAdded = 2)] - private string server; - private string message; - private string procedure; - private int lineNumber; - [System.Runtime.Serialization.OptionalFieldAttribute(VersionAdded = 4)] - private int win32ErrorCode; + private readonly string _source = TdsEnums.SQL_PROVIDER_NAME; + private readonly int _number; + private readonly byte _state; + private readonly byte _errorClass; + [System.Runtime.Serialization.OptionalField(VersionAdded = 2)] + private readonly string _server; + private readonly string _message; + private readonly string _procedure; + private readonly int _lineNumber; + [System.Runtime.Serialization.OptionalField(VersionAdded = 4)] + private readonly int _win32ErrorCode; internal SqlError(int infoNumber, byte errorState, byte errorClass, string server, string errorMessage, string procedure, int lineNumber, uint win32ErrorCode) : this(infoNumber, errorState, errorClass, server, errorMessage, procedure, lineNumber) { - this.win32ErrorCode = (int)win32ErrorCode; + _win32ErrorCode = (int)win32ErrorCode; } internal SqlError(int infoNumber, byte errorState, byte errorClass, string server, string errorMessage, string procedure, int lineNumber) { - this.number = infoNumber; - this.state = errorState; - this.errorClass = errorClass; - this.server = server; - this.message = errorMessage; - this.procedure = procedure; - this.lineNumber = lineNumber; + _number = infoNumber; + _state = errorState; + _errorClass = errorClass; + _server = server; + _message = errorMessage; + _procedure = procedure; + _lineNumber = lineNumber; if (errorClass != 0) { SqlClientEventSource.Log.TraceEvent(" infoNumber={0}, errorState={1}, errorClass={2}, errorMessage='{3}', procedure='{4}', lineNumber={5}", infoNumber, (int)errorState, (int)errorClass, errorMessage, procedure ?? "None", (int)lineNumber); } - this.win32ErrorCode = 0; + _win32ErrorCode = 0; } - /// + /// // bug fix - MDAC #49280 - SqlError does not implement ToString(); // I did not include an exception stack because the correct exception stack is only available // on SqlException, and to obtain that the SqlError would have to have backpointers all the // way back to SqlException. If the user needs a call stack, they can obtain it on SqlException. public override string ToString() { - //return this.GetType().ToString() + ": " + this.message; - return typeof(SqlError).ToString() + ": " + this.message; // since this is sealed so we can change GetType to typeof + //return GetType().ToString() + ": " + message; + return typeof(SqlError).ToString() + ": " + _message; // since this is sealed so we can change GetType to typeof } - /// + /// // bug fix - MDAC #48965 - missing source of exception public string Source { - get { return this.source; } + get { return _source; } } - /// + /// public int Number { - get { return this.number; } + get { return _number; } } - /// + /// public byte State { - get { return this.state; } + get { return _state; } } - /// + /// public byte Class { - get { return this.errorClass; } + get { return _errorClass; } } - /// + /// public string Server { - get { return this.server; } + get { return _server; } } - /// + /// public string Message { - get { return this.message; } + get { return _message; } } - /// + /// public string Procedure { - get { return this.procedure; } + get { return _procedure; } } - /// + /// public int LineNumber { - get { return this.lineNumber; } + get { return _lineNumber; } } internal int Win32ErrorCode { - get { return this.win32ErrorCode; } + get { return _win32ErrorCode; } } } } diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlException.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlException.cs index 627861e6e5..7e4fe9f411 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlException.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlException.cs @@ -99,43 +99,43 @@ private bool ShouldSerializeErrors() /// public byte Class { - get { return this.Errors[0].Class; } + get { return Errors.Count > 0 ? Errors[0].Class : default; } } /// public int LineNumber { - get { return this.Errors[0].LineNumber; } + get { return Errors.Count > 0 ? Errors[0].LineNumber : default; } } /// public int Number { - get { return this.Errors[0].Number; } + get { return Errors.Count > 0 ? Errors[0].Number : default; } } /// public string Procedure { - get { return this.Errors[0].Procedure; } + get { return Errors.Count > 0 ? Errors[0].Procedure : default; } } /// public string Server { - get { return this.Errors[0].Server; } + get { return Errors.Count > 0 ? Errors[0].Server : default; } } /// public byte State { - get { return this.Errors[0].State; } + get { return Errors.Count > 0 ? Errors[0].State : default; } } /// override public string Source { - get { return this.Errors[0].Source; } + get { return TdsEnums.SQL_PROVIDER_NAME; } } /// @@ -146,7 +146,7 @@ public override string ToString() sb.AppendFormat(SQLMessage.ExClientConnectionId(), _clientConnectionId); // Append the error number, state and class if the server provided it - if (Number != 0) + if (Errors.Count > 0 && Number != 0) { sb.AppendLine(); sb.AppendFormat(SQLMessage.ExErrorNumberStateClass(), Number, State, Class); @@ -169,12 +169,12 @@ public override string ToString() return sb.ToString(); } - static internal SqlException CreateException(SqlErrorCollection errorCollection, string serverVersion) + internal static SqlException CreateException(SqlErrorCollection errorCollection, string serverVersion) { return CreateException(errorCollection, serverVersion, Guid.Empty); } - static internal SqlException CreateException(SqlErrorCollection errorCollection, string serverVersion, SqlInternalConnectionTds internalConnection, Exception innerException = null) + internal static SqlException CreateException(SqlErrorCollection errorCollection, string serverVersion, SqlInternalConnectionTds internalConnection, Exception innerException = null) { Guid connectionId = (internalConnection == null) ? Guid.Empty : internalConnection._clientConnectionId; var exception = CreateException(errorCollection, serverVersion, connectionId, innerException); @@ -195,11 +195,10 @@ static internal SqlException CreateException(SqlErrorCollection errorCollection, return exception; } - static internal SqlException CreateException(SqlErrorCollection errorCollection, string serverVersion, Guid conId, Exception innerException = null) + internal static SqlException CreateException(SqlErrorCollection errorCollection, string serverVersion, Guid conId, Exception innerException = null) { Debug.Assert(null != errorCollection && errorCollection.Count > 0, "no errorCollection?"); - // concat all messages together MDAC 65533 StringBuilder message = new StringBuilder(); for (int i = 0; i < errorCollection.Count; i++) { @@ -219,7 +218,7 @@ static internal SqlException CreateException(SqlErrorCollection errorCollection, exception.Data.Add("HelpLink.ProdName", "Microsoft SQL Server"); - if (!ADP.IsEmpty(serverVersion)) + if (!string.IsNullOrEmpty(serverVersion)) { exception.Data.Add("HelpLink.ProdVer", serverVersion); }