Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix | Perform Null check for SqlErrors in SqlException #698

Merged
merged 2 commits into from
Aug 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 18 additions & 8 deletions doc/snippets/Microsoft.Data.SqlClient/SqlException.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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 <xref:Microsoft.Data.SqlClient.SqlError.Class%2A> property of the first <xref:Microsoft.Data.SqlClient.SqlError> in the <xref:Microsoft.Data.SqlClient.SqlException.Errors%2A> property.


If <xref:Microsoft.Data.SqlClient.SqlException.Errors%2A> is `null`, the [`default`](https://docs.microsoft.com/dotnet/csharp/language-reference/builtin-types/default-values) value for `byte` is returned.



## Examples
Expand Down Expand Up @@ -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 <xref:Microsoft.Data.SqlClient.SqlError.LineNumber%2A> property of the first <xref:Microsoft.Data.SqlClient.SqlError> in the <xref:Microsoft.Data.SqlClient.SqlException.Errors%2A> property.


If <xref:Microsoft.Data.SqlClient.SqlException.Errors%2A> is `null`, the [`default`](https://docs.microsoft.com/dotnet/csharp/language-reference/builtin-types/default-values) value for `int` is returned.



## Examples
Expand Down Expand Up @@ -190,7 +194,11 @@ catch (Exception ex) {
<format type="text/markdown"><![CDATA[

## Remarks
This is a wrapper for the <xref:Microsoft.Data.SqlClient.SqlError.Number%2A> property of the first <xref:Microsoft.Data.SqlClient.SqlError> in the <xref:Microsoft.Data.SqlClient.SqlException.Errors%2A> 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 <xref:Microsoft.Data.SqlClient.SqlError.Number%2A> property of the first <xref:Microsoft.Data.SqlClient.SqlError> in the <xref:Microsoft.Data.SqlClient.SqlException.Errors%2A> property.

If <xref:Microsoft.Data.SqlClient.SqlException.Errors%2A> 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).



Expand All @@ -215,8 +223,9 @@ catch (Exception ex) {
<format type="text/markdown"><![CDATA[

## Remarks
This is a wrapper for the <xref:Microsoft.Data.SqlClient.SqlError.Procedure%2A> property of the first <xref:Microsoft.Data.SqlClient.SqlError> in the <xref:Microsoft.Data.SqlClient.SqlException.Errors%2A> property.

This is a wrapper for the <xref:Microsoft.Data.SqlClient.SqlError.Procedure%2A> property of the first <xref:Microsoft.Data.SqlClient.SqlError> in the <xref:Microsoft.Data.SqlClient.SqlException.Errors%2A> property.

If <xref:Microsoft.Data.SqlClient.SqlException.Errors%2A> is `null`, the [`default`](https://docs.microsoft.com/dotnet/csharp/language-reference/builtin-types/default-values) value for `string` is returned.


## Examples
Expand All @@ -241,7 +250,8 @@ catch (Exception ex) {

## Remarks
This is a wrapper for the <xref:Microsoft.Data.SqlClient.SqlError.Server%2A> property of the first <xref:Microsoft.Data.SqlClient.SqlError> in the <xref:Microsoft.Data.SqlClient.SqlException.Errors%2A> property.


If <xref:Microsoft.Data.SqlClient.SqlException.Errors%2A> is `null`, the [`default`](https://docs.microsoft.com/dotnet/csharp/language-reference/builtin-types/default-values) value for `string` is returned.


## Examples
Expand All @@ -266,7 +276,6 @@ catch (Exception ex) {

## Remarks
This is a wrapper for the <xref:Microsoft.Data.SqlClient.SqlError.Source%2A> property of the first <xref:Microsoft.Data.SqlClient.SqlError> in the <xref:Microsoft.Data.SqlClient.SqlException.Errors%2A> property.



## Examples
Expand All @@ -291,7 +300,8 @@ catch (Exception ex) {

## Remarks
This is a wrapper for the <xref:Microsoft.Data.SqlClient.SqlError.State%2A> property of the first <xref:Microsoft.Data.SqlClient.SqlError> in the <xref:Microsoft.Data.SqlClient.SqlException.Errors%2A> property.


If <xref:Microsoft.Data.SqlClient.SqlException.Errors%2A> is `null`, the [`default`](https://docs.microsoft.com/dotnet/csharp/language-reference/builtin-types/default-values) value for `byte` is returned.


## Examples
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,23 @@ namespace Microsoft.Data.SqlClient
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/SqlError/*' />
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("<sc.SqlError.SqlError|ERR> infoNumber={0}, errorState={1}, errorClass={2}, errorMessage='{3}', procedure='{4}', lineNumber={5}", infoNumber, (int)errorState, (int)errorClass, errorMessage, procedure ?? "None", (int)lineNumber);
Expand All @@ -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
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/Source/*' />
public string Source
{
get { return _source; }
}
public string Source { get; private set; } = TdsEnums.SQL_PROVIDER_NAME;

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/Number/*' />
public int Number
{
get { return _number; }
}
public int Number { get; private set; }

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/State/*' />
public byte State
{
get { return _state; }
}
public byte State { get; private set; }

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/Class/*' />
public byte Class
{
get { return _errorClass; }
}
public byte Class { get; private set; }

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/Server/*' />
public string Server
{
get { return _server; }
}
public string Server { get; private set; }

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/Message/*' />
public string Message
{
get { return _message; }
}
public string Message { get; private set; }

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/Procedure/*' />
public string Procedure
{
get { return _procedure; }
}
public string Procedure { get; private set; }

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/LineNumber/*' />
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; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public Guid ClientConnectionId
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlException.xml' path='docs/members[@name="SqlException"]/Class/*' />
public byte Class
{
get { return Errors.Count > 0 ? this.Errors[0].Class : default; }
get { return Errors.Count > 0 ? Errors[0].Class : default; }
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlException.xml' path='docs/members[@name="SqlException"]/LineNumber/*' />
Expand Down Expand Up @@ -125,7 +125,7 @@ public byte State
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlException.xml' path='docs/members[@name="SqlException"]/Source/*' />
override public string Source
{
get { return Errors.Count > 0 ? Errors[0].Source : default; }
get { return TdsEnums.SQL_PROVIDER_NAME; }
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlException.xml' path='docs/members[@name="SqlException"]/ToString/*' />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,109 +6,108 @@

namespace Microsoft.Data.SqlClient
{
/// <include file='..\..\..\..\..\..\..\doc\snippets\Microsoft.Data.SqlClient\SqlError.xml' path='docs/members[@name="SqlError"]/SqlError/*' />
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/SqlError/*' />
[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("<sc.SqlError.SqlError|ERR> 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;
}

/// <include file='..\..\..\..\..\..\..\doc\snippets\Microsoft.Data.SqlClient\SqlError.xml' path='docs/members[@name="SqlError"]/ToString/*' />
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/ToString/*' />
// 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
}

/// <include file='..\..\..\..\..\..\..\doc\snippets\Microsoft.Data.SqlClient\SqlError.xml' path='docs/members[@name="SqlError"]/Source/*' />
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/Source/*' />
// bug fix - MDAC #48965 - missing source of exception
public string Source
{
get { return this.source; }
get { return _source; }
}

/// <include file='..\..\..\..\..\..\..\doc\snippets\Microsoft.Data.SqlClient\SqlError.xml' path='docs/members[@name="SqlError"]/Number/*' />
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/Number/*' />
public int Number
{
get { return this.number; }
get { return _number; }
}

/// <include file='..\..\..\..\..\..\..\doc\snippets\Microsoft.Data.SqlClient\SqlError.xml' path='docs/members[@name="SqlError"]/State/*' />
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/State/*' />
public byte State
{
get { return this.state; }
get { return _state; }
}

/// <include file='..\..\..\..\..\..\..\doc\snippets\Microsoft.Data.SqlClient\SqlError.xml' path='docs/members[@name="SqlError"]/Class/*' />
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/Class/*' />
public byte Class
{
get { return this.errorClass; }
get { return _errorClass; }
}

/// <include file='..\..\..\..\..\..\..\doc\snippets\Microsoft.Data.SqlClient\SqlError.xml' path='docs/members[@name="SqlError"]/Server/*' />
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/Server/*' />
public string Server
{
get { return this.server; }
get { return _server; }
}

/// <include file='..\..\..\..\..\..\..\doc\snippets\Microsoft.Data.SqlClient\SqlError.xml' path='docs/members[@name="SqlError"]/Message/*' />
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/Message/*' />
public string Message
{
get { return this.message; }
get { return _message; }
}

/// <include file='..\..\..\..\..\..\..\doc\snippets\Microsoft.Data.SqlClient\SqlError.xml' path='docs/members[@name="SqlError"]/Procedure/*' />
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/Procedure/*' />
public string Procedure
{
get { return this.procedure; }
get { return _procedure; }
}

/// <include file='..\..\..\..\..\..\..\doc\snippets\Microsoft.Data.SqlClient\SqlError.xml' path='docs/members[@name="SqlError"]/LineNumber/*' />
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/LineNumber/*' />
public int LineNumber
{
get { return this.lineNumber; }
get { return _lineNumber; }
}

internal int Win32ErrorCode
{
get { return this.win32ErrorCode; }
get { return _win32ErrorCode; }
}
}
}
Loading