@@ -63,176 +63,158 @@ NOTE: The connection string for server name is geared toward Azure SQL Database,
6363
6464
6565``` csharp
66- using System ; // C#
67- using CG = System .Collections .Generic ;
68- using QC = Microsoft .Data .SqlClient ;
69- using TD = System .Threading ;
70-
71- namespace RetryAdo2
72- {
73- public class Program
74- {
75- static public int Main (string [] args )
76- {
77- bool succeeded = false ;
78- int totalNumberOfTimesToTry = 4 ;
79- int retryIntervalSeconds = 10 ;
80-
81- for (int tries = 1 ;
82- tries <= totalNumberOfTimesToTry ;
83- tries ++ )
84- {
85- try
86- {
87- if (tries > 1 )
88- {
89- Console .WriteLine
90- (" Transient error encountered. Will begin attempt number {0} of {1} max..." ,
91- tries , totalNumberOfTimesToTry
92- );
93- TD .Thread .Sleep (1000 * retryIntervalSeconds );
94- retryIntervalSeconds = Convert .ToInt32
95- (retryIntervalSeconds * 1 . 5 );
96- }
97- AccessDatabase ();
98- succeeded = true ;
99- break ;
100- }
101-
102- catch (QC .SqlException sqlExc )
103- {
104- if (TransientErrorNumbers .Contains
105- (sqlExc .Number ) == true )
106- {
107- Console .WriteLine (" {0}: transient occurred." , sqlExc .Number );
108- continue ;
109- }
110- else
111- {
112- Console .WriteLine (sqlExc );
113- succeeded = false ;
114- break ;
115- }
116- }
117-
118- catch (TestSqlException sqlExc )
119- {
120- if (TransientErrorNumbers .Contains
121- (sqlExc .Number ) == true )
122- {
123- Console .WriteLine (" {0}: transient occurred. (TESTING.)" , sqlExc .Number );
124- continue ;
125- }
126- else
127- {
128- Console .WriteLine (sqlExc );
129- succeeded = false ;
130- break ;
131- }
132- }
133-
134- catch (Exception Exc )
135- {
136- Console .WriteLine (Exc );
137- succeeded = false ;
138- break ;
139- }
140- }
141-
142- if (succeeded == true )
143- {
144- return 0 ;
145- }
146- else
147- {
148- Console .WriteLine (" ERROR: Unable to access the database!" );
149- return 1 ;
150- }
151- }
152-
153- /// <summary >
154- /// Connects to the database, reads,
155- /// prints results to the console.
156- /// </summary >
157- static public void AccessDatabase ()
158- {
159- // throw new TestSqlException(4060); //(7654321); // Uncomment for testing.
160-
161- using (var sqlConnection = new QC .SqlConnection
162- (GetSqlConnectionString ()))
163- {
164- using (var dbCommand = sqlConnection .CreateCommand ())
165- {
166- dbCommand .CommandText = @"
66+ using System ;
67+ using System .Collections .Generic ;
68+ using Microsoft .Data .SqlClient ;
69+ using System .Threading ;
70+
71+ namespace RetryAdo2 ;
72+
73+ public class Program
74+ {
75+ public static int Main (string [] args )
76+ {
77+ bool succeeded = false ;
78+ const int totalNumberOfTimesToTry = 4 ;
79+ int retryIntervalSeconds = 10 ;
80+
81+ for (int tries = 1 ; tries <= totalNumberOfTimesToTry ; tries ++ )
82+ {
83+ try
84+ {
85+ if (tries > 1 )
86+ {
87+ Console .WriteLine (
88+ " Transient error encountered. Will begin attempt number {0} of {1} max..." ,
89+ tries ,
90+ totalNumberOfTimesToTry
91+ );
92+ Thread .Sleep (1000 * retryIntervalSeconds );
93+ retryIntervalSeconds = Convert .ToInt32 (retryIntervalSeconds * 1 . 5 );
94+ }
95+ AccessDatabase ();
96+ succeeded = true ;
97+ break ;
98+ }
99+ catch (SqlException sqlExc ) {
100+ if (TransientErrorNumbers .Contains (sqlExc .Number ))
101+ {
102+ Console .WriteLine (" {0}: transient occurred." , sqlExc .Number );
103+ continue ;
104+ }
105+
106+ Console .WriteLine (sqlExc );
107+ succeeded = false ;
108+ break ;
109+ }
110+ catch (TestSqlException sqlExc ) {
111+ if (TransientErrorNumbers .Contains (sqlExc .Number ))
112+ {
113+ Console .WriteLine (" {0}: transient occurred. (TESTING.)" , sqlExc .Number );
114+ continue ;
115+ }
116+
117+ Console .WriteLine (sqlExc );
118+ succeeded = false ;
119+ break ;
120+ }
121+ catch (Exception e )
122+ {
123+ Console .WriteLine (e );
124+ succeeded = false ;
125+ break ;
126+ }
127+ }
128+
129+ if (! succeeded ) {
130+ Console .WriteLine (" ERROR: Unable to access the database!" );
131+ return 1 ;
132+ }
133+
134+ return 0 ;
135+ }
136+
137+ /// <summary >
138+ /// Connects to the database, reads,
139+ /// prints results to the console.
140+ /// </summary >
141+ static void AccessDatabase () {
142+ // throw new TestSqlException(4060); //(7654321); // Uncomment for testing.
143+
144+ using var sqlConnection = new SqlConnection (GetSqlConnectionString ());
145+
146+ using var dbCommand = sqlConnection .CreateCommand ();
147+
148+ dbCommand .CommandText =
149+ @"
167150SELECT TOP 3
168151 ob.name,
169152 CAST(ob.object_id as nvarchar(32)) as [object_id]
170153 FROM sys.objects as ob
171154 WHERE ob.type='IT'
172- ORDER BY ob.name;" ;
173-
174- sqlConnection .Open ();
175- var dataReader = dbCommand .ExecuteReader ();
176-
177- while (dataReader .Read ())
178- {
179- Console .WriteLine (" {0}\t {1}" ,
180- dataReader .GetString (0 ),
181- dataReader .GetString (1 ));
182- }
183- }
184- }
185- }
186-
187- /// <summary >
188- /// You must edit the four 'my' string values.
189- /// </summary >
190- /// <returns >An ADO.NET connection string.</returns >
191- static private string GetSqlConnectionString ()
192- {
193- // Prepare the connection string to Azure SQL Database.
194- var sqlConnectionSB = new QC .SqlConnectionStringBuilder ();
195-
196- // Change these values to your values.
197- sqlConnectionSB .DataSource = " tcp:myazuresqldbserver.database.windows.net,1433" ; // ["Server"]
198- sqlConnectionSB .InitialCatalog = " MyDatabase" ; // ["Database"]
199-
200- sqlConnectionSB .UserID = " MyLogin" ; // "@yourservername" as suffix sometimes.
201- sqlConnectionSB .Password = " MyPassword" ;
202-
203- // Adjust these values if you like. (ADO.NET 4.5.1 or later.)
204- sqlConnectionSB .ConnectRetryCount = 3 ;
205- sqlConnectionSB .ConnectRetryInterval = 10 ; // Seconds.
206-
207- // Leave these values as they are.
208- sqlConnectionSB .IntegratedSecurity = false ;
209- sqlConnectionSB .Encrypt = true ;
210- sqlConnectionSB .ConnectTimeout = 30 ;
211-
212- return sqlConnectionSB .ToString ();
213- }
214-
215- static public CG.List <int > TransientErrorNumbers =
216- new CG .List <int > { 4060 , 40197 , 40501 , 40613 ,
217- 49918 , 49919 , 49920 , 11001 };
218- }
219-
220- /// <summary >
221- /// For testing retry logic, you can have method
222- /// AccessDatabase start by throwing a new
223- /// TestSqlException with a Number that does
224- /// or does not match a transient error number
225- /// present in TransientErrorNumbers.
226- /// </summary >
227- internal class TestSqlException : ApplicationException
228- {
229- internal TestSqlException (int testErrorNumber )
230- { this .Number = testErrorNumber ; }
231-
232- internal int Number
233- { get ; set ; }
234- }
235- }
155+ ORDER BY ob.name;" ;
156+
157+ sqlConnection .Open ();
158+ var dataReader = dbCommand .ExecuteReader ();
159+
160+ while (dataReader .Read ())
161+ {
162+ Console .WriteLine (
163+ " {0}\t {1}" ,
164+ dataReader .GetString (0 ),
165+ dataReader .GetString (1 )
166+ );
167+ }
168+ }
169+
170+ /// <summary >
171+ /// You must edit the four 'my' string values.
172+ /// </summary >
173+ /// <returns >An ADO.NET connection string.</returns >
174+ static private string GetSqlConnectionString ()
175+ {
176+ // Prepare the connection string to Azure SQL Database.
177+ var sqlConnectionSB = new SqlConnectionStringBuilder
178+ {
179+ // Change these values to your values.
180+ DataSource = " tcp:myazuresqldbserver.database.windows.net,1433" , // ["Server"]
181+ InitialCatalog = " MyDatabase" , // ["Database"]
182+ UserID = " MyLogin" , // "@yourservername" as suffix sometimes.
183+ Password = " MyPassword" ,
184+ // Adjust these values if you like. (ADO.NET 4.5.1 or later.)
185+ ConnectRetryCount = 3 ,
186+ ConnectRetryInterval = 10 , // Seconds.
187+ // Leave these values as they are.
188+ IntegratedSecurity = false ,
189+ Encrypt = true ,
190+ ConnectTimeout = 30
191+ };
192+
193+ return sqlConnectionSB .ToString ();
194+ }
195+
196+ static List <int > TransientErrorNumbers = new ()
197+ {
198+ 4060 , 40197 , 40501 , 40613 , 49918 , 49919 , 49920 , 11001
199+ };
200+ }
201+
202+ /// <summary >
203+ /// For testing retry logic, you can have method
204+ /// AccessDatabase start by throwing a new
205+ /// TestSqlException with a Number that does
206+ /// or does not match a transient error number
207+ /// present in TransientErrorNumbers.
208+ /// </summary >
209+ internal class TestSqlException : ApplicationException
210+ {
211+ internal TestSqlException (int testErrorNumber )
212+ {
213+ Number = testErrorNumber ;
214+ }
215+
216+ internal int Number { get ; set ; }
217+ }
236218```
237219
238220### Step 2.c: Run the program
0 commit comments