Skip to content

Commit e10b230

Browse files
Fix | Perform Null check for SqlErrors in SqlException (#698)
1 parent ec6a263 commit e10b230

File tree

5 files changed

+94
-127
lines changed

5 files changed

+94
-127
lines changed

doc/snippets/Microsoft.Data.SqlClient/SqlException.xml

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ catch (Exception ex) {
8585
For information about the warning and informational messages sent by SQL Server, see the Troubleshooting section of the SQL Server documentation.
8686
8787
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.
88-
88+
89+
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.
90+
8991
9092
9193
## Examples
@@ -161,7 +163,9 @@ catch (Exception ex) {
161163
The line numbering starts at 1; if 0 is returned, the line number is not applicable.
162164
163165
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.
164-
166+
167+
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.
168+
165169
166170
167171
## Examples
@@ -190,7 +194,11 @@ catch (Exception ex) {
190194
<format type="text/markdown"><![CDATA[
191195
192196
## Remarks
193-
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).
197+
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.
198+
199+
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.
200+
201+
For more information on SQL Server engine errors, see [Database Engine Events and Errors](/sql/relational-databases/errors-events/database-engine-events-and-errors).
194202
195203
196204
@@ -215,8 +223,9 @@ catch (Exception ex) {
215223
<format type="text/markdown"><![CDATA[
216224
217225
## Remarks
218-
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.
219-
226+
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.
227+
228+
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.
220229
221230
222231
## Examples
@@ -241,7 +250,8 @@ catch (Exception ex) {
241250
242251
## Remarks
243252
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.
244-
253+
254+
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.
245255
246256
247257
## Examples
@@ -266,7 +276,6 @@ catch (Exception ex) {
266276
267277
## Remarks
268278
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.
269-
270279
271280
272281
## Examples
@@ -291,7 +300,8 @@ catch (Exception ex) {
291300
292301
## Remarks
293302
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.
294-
303+
304+
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.
295305
296306
297307
## Examples

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlError.cs

Lines changed: 21 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -9,34 +9,23 @@ namespace Microsoft.Data.SqlClient
99
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/SqlError/*' />
1010
public sealed class SqlError
1111
{
12-
private string _source = TdsEnums.SQL_PROVIDER_NAME;
13-
private int _number;
14-
private byte _state;
15-
private byte _errorClass;
16-
private string _server;
17-
private string _message;
18-
private string _procedure;
19-
private int _lineNumber;
20-
private int _win32ErrorCode;
21-
private Exception _exception;
22-
2312
internal SqlError(int infoNumber, byte errorState, byte errorClass, string server, string errorMessage, string procedure, int lineNumber, uint win32ErrorCode, Exception exception = null)
2413
: this(infoNumber, errorState, errorClass, server, errorMessage, procedure, lineNumber, exception)
2514
{
26-
_win32ErrorCode = (int)win32ErrorCode;
15+
Win32ErrorCode = (int)win32ErrorCode;
2716
}
2817

2918
internal SqlError(int infoNumber, byte errorState, byte errorClass, string server, string errorMessage, string procedure, int lineNumber, Exception exception = null)
3019
{
31-
_number = infoNumber;
32-
_state = errorState;
33-
_errorClass = errorClass;
34-
_server = server;
35-
_message = errorMessage;
36-
_procedure = procedure;
37-
_lineNumber = lineNumber;
38-
_win32ErrorCode = 0;
39-
_exception = exception;
20+
Number = infoNumber;
21+
State = errorState;
22+
Class = errorClass;
23+
Server = server;
24+
Message = errorMessage;
25+
Procedure = procedure;
26+
LineNumber = lineNumber;
27+
Win32ErrorCode = 0;
28+
Exception = exception;
4029
if (errorClass != 0)
4130
{
4231
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);
@@ -49,65 +38,35 @@ internal SqlError(int infoNumber, byte errorState, byte errorClass, string serve
4938
// way back to SqlException. If the user needs a call stack, they can obtain it on SqlException.
5039
public override string ToString()
5140
{
52-
return typeof(SqlError).ToString() + ": " + _message; // since this is sealed so we can change GetType to typeof
41+
return typeof(SqlError).ToString() + ": " + Message; // since this is sealed so we can change GetType to typeof
5342
}
5443

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

6147
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/Number/*' />
62-
public int Number
63-
{
64-
get { return _number; }
65-
}
48+
public int Number { get; private set; }
6649

6750
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/State/*' />
68-
public byte State
69-
{
70-
get { return _state; }
71-
}
51+
public byte State { get; private set; }
7252

7353
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/Class/*' />
74-
public byte Class
75-
{
76-
get { return _errorClass; }
77-
}
54+
public byte Class { get; private set; }
7855

7956
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/Server/*' />
80-
public string Server
81-
{
82-
get { return _server; }
83-
}
57+
public string Server { get; private set; }
8458

8559
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/Message/*' />
86-
public string Message
87-
{
88-
get { return _message; }
89-
}
60+
public string Message { get; private set; }
9061

9162
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/Procedure/*' />
92-
public string Procedure
93-
{
94-
get { return _procedure; }
95-
}
63+
public string Procedure { get; private set; }
9664

9765
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/LineNumber/*' />
98-
public int LineNumber
99-
{
100-
get { return _lineNumber; }
101-
}
66+
public int LineNumber { get; private set; }
10267

103-
internal int Win32ErrorCode
104-
{
105-
get { return _win32ErrorCode; }
106-
}
68+
internal int Win32ErrorCode { get; private set; }
10769

108-
internal Exception Exception
109-
{
110-
get { return _exception; }
111-
}
70+
internal Exception Exception { get; private set; }
11271
}
11372
}

src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlException.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public Guid ClientConnectionId
8989
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlException.xml' path='docs/members[@name="SqlException"]/Class/*' />
9090
public byte Class
9191
{
92-
get { return Errors.Count > 0 ? this.Errors[0].Class : default; }
92+
get { return Errors.Count > 0 ? Errors[0].Class : default; }
9393
}
9494

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

131131
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlException.xml' path='docs/members[@name="SqlException"]/ToString/*' />

src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlError.cs

Lines changed: 41 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6,109 +6,108 @@
66

77
namespace Microsoft.Data.SqlClient
88
{
9-
/// <include file='..\..\..\..\..\..\..\doc\snippets\Microsoft.Data.SqlClient\SqlError.xml' path='docs/members[@name="SqlError"]/SqlError/*' />
9+
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/SqlError/*' />
1010
[Serializable]
1111
public sealed class SqlError
1212
{
13-
1413
// bug fix - MDAC 48965 - missing source of exception
15-
private string source = TdsEnums.SQL_PROVIDER_NAME;
16-
private int number;
17-
private byte state;
18-
private byte errorClass;
19-
[System.Runtime.Serialization.OptionalFieldAttribute(VersionAdded = 2)]
20-
private string server;
21-
private string message;
22-
private string procedure;
23-
private int lineNumber;
24-
[System.Runtime.Serialization.OptionalFieldAttribute(VersionAdded = 4)]
25-
private int win32ErrorCode;
14+
private readonly string _source = TdsEnums.SQL_PROVIDER_NAME;
15+
private readonly int _number;
16+
private readonly byte _state;
17+
private readonly byte _errorClass;
18+
[System.Runtime.Serialization.OptionalField(VersionAdded = 2)]
19+
private readonly string _server;
20+
private readonly string _message;
21+
private readonly string _procedure;
22+
private readonly int _lineNumber;
23+
[System.Runtime.Serialization.OptionalField(VersionAdded = 4)]
24+
private readonly int _win32ErrorCode;
2625

2726
internal SqlError(int infoNumber, byte errorState, byte errorClass, string server, string errorMessage, string procedure, int lineNumber, uint win32ErrorCode)
2827
: this(infoNumber, errorState, errorClass, server, errorMessage, procedure, lineNumber)
2928
{
30-
this.win32ErrorCode = (int)win32ErrorCode;
29+
_win32ErrorCode = (int)win32ErrorCode;
3130
}
3231

3332
internal SqlError(int infoNumber, byte errorState, byte errorClass, string server, string errorMessage, string procedure, int lineNumber)
3433
{
35-
this.number = infoNumber;
36-
this.state = errorState;
37-
this.errorClass = errorClass;
38-
this.server = server;
39-
this.message = errorMessage;
40-
this.procedure = procedure;
41-
this.lineNumber = lineNumber;
34+
_number = infoNumber;
35+
_state = errorState;
36+
_errorClass = errorClass;
37+
_server = server;
38+
_message = errorMessage;
39+
_procedure = procedure;
40+
_lineNumber = lineNumber;
4241
if (errorClass != 0)
4342
{
4443
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);
4544
}
46-
this.win32ErrorCode = 0;
45+
_win32ErrorCode = 0;
4746
}
4847

49-
/// <include file='..\..\..\..\..\..\..\doc\snippets\Microsoft.Data.SqlClient\SqlError.xml' path='docs/members[@name="SqlError"]/ToString/*' />
48+
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/ToString/*' />
5049
// bug fix - MDAC #49280 - SqlError does not implement ToString();
5150
// I did not include an exception stack because the correct exception stack is only available
5251
// on SqlException, and to obtain that the SqlError would have to have backpointers all the
5352
// way back to SqlException. If the user needs a call stack, they can obtain it on SqlException.
5453
public override string ToString()
5554
{
56-
//return this.GetType().ToString() + ": " + this.message;
57-
return typeof(SqlError).ToString() + ": " + this.message; // since this is sealed so we can change GetType to typeof
55+
//return GetType().ToString() + ": " + message;
56+
return typeof(SqlError).ToString() + ": " + _message; // since this is sealed so we can change GetType to typeof
5857
}
5958

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

67-
/// <include file='..\..\..\..\..\..\..\doc\snippets\Microsoft.Data.SqlClient\SqlError.xml' path='docs/members[@name="SqlError"]/Number/*' />
66+
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/Number/*' />
6867
public int Number
6968
{
70-
get { return this.number; }
69+
get { return _number; }
7170
}
7271

73-
/// <include file='..\..\..\..\..\..\..\doc\snippets\Microsoft.Data.SqlClient\SqlError.xml' path='docs/members[@name="SqlError"]/State/*' />
72+
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/State/*' />
7473
public byte State
7574
{
76-
get { return this.state; }
75+
get { return _state; }
7776
}
7877

79-
/// <include file='..\..\..\..\..\..\..\doc\snippets\Microsoft.Data.SqlClient\SqlError.xml' path='docs/members[@name="SqlError"]/Class/*' />
78+
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/Class/*' />
8079
public byte Class
8180
{
82-
get { return this.errorClass; }
81+
get { return _errorClass; }
8382
}
8483

85-
/// <include file='..\..\..\..\..\..\..\doc\snippets\Microsoft.Data.SqlClient\SqlError.xml' path='docs/members[@name="SqlError"]/Server/*' />
84+
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/Server/*' />
8685
public string Server
8786
{
88-
get { return this.server; }
87+
get { return _server; }
8988
}
9089

91-
/// <include file='..\..\..\..\..\..\..\doc\snippets\Microsoft.Data.SqlClient\SqlError.xml' path='docs/members[@name="SqlError"]/Message/*' />
90+
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/Message/*' />
9291
public string Message
9392
{
94-
get { return this.message; }
93+
get { return _message; }
9594
}
9695

97-
/// <include file='..\..\..\..\..\..\..\doc\snippets\Microsoft.Data.SqlClient\SqlError.xml' path='docs/members[@name="SqlError"]/Procedure/*' />
96+
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/Procedure/*' />
9897
public string Procedure
9998
{
100-
get { return this.procedure; }
99+
get { return _procedure; }
101100
}
102101

103-
/// <include file='..\..\..\..\..\..\..\doc\snippets\Microsoft.Data.SqlClient\SqlError.xml' path='docs/members[@name="SqlError"]/LineNumber/*' />
102+
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlError.xml' path='docs/members[@name="SqlError"]/LineNumber/*' />
104103
public int LineNumber
105104
{
106-
get { return this.lineNumber; }
105+
get { return _lineNumber; }
107106
}
108107

109108
internal int Win32ErrorCode
110109
{
111-
get { return this.win32ErrorCode; }
110+
get { return _win32ErrorCode; }
112111
}
113112
}
114113
}

0 commit comments

Comments
 (0)