Skip to content

Commit bb706fc

Browse files
authored
Create ResilientDBApp.program
1 parent 8c77d78 commit bb706fc

1 file changed

Lines changed: 193 additions & 0 deletions

File tree

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
using System;
2+
using System.Configuration; // use App.config file
3+
using System.Collections.Specialized;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
using System.Data.SqlClient; // use SQL client library
9+
using CG = System.Collections.Generic;
10+
using TD = System.Threading;
11+
using QC = System.Data.SqlClient;
12+
13+
namespace ResilientDBApp
14+
{
15+
public class Program
16+
{
17+
static void Main(string[] args)
18+
{
19+
// Query executions and waits
20+
int executions = 100; // how many executions
21+
int sleeptime = 2; // wait time between executions (seconds)
22+
23+
// Connection parameters and resiliency options
24+
string InstanceConnectionString = "ConnMI1"; // connection string to SQL MI
25+
bool ResilientQuery = true; // execute resilient, or non-resilient query to transient errors (retry logic true/false)
26+
27+
// Query text to execute
28+
string SQLtext = "INSERT INTO timetable (datestamp) VALUES (CURRENT_TIMESTAMP);";
29+
bool ReadBack = false; // read query response from SQL MI - if using SELECT statements
30+
31+
try
32+
{
33+
for (int i = 1; i <= executions; i++)
34+
{
35+
Console.Write("Execution # {0} ", i);
36+
if (!ResilientQuery)
37+
{
38+
Console.WriteLine ("(NON-RESILIENT)");
39+
InsertNonResilient(SQLtext, InstanceConnectionString, ReadBack); // execute NON-resilient DB query - NO retry logic
40+
} else
41+
{
42+
Console.WriteLine("(RESILIENT)");
43+
InsertResilient(SQLtext, InstanceConnectionString, ReadBack); // execute resilient DB query - HAS RETRY LOGIC
44+
}
45+
TD.Thread.Sleep(1000 * sleeptime); // wait between the queries
46+
}
47+
}
48+
catch (Exception e)
49+
{
50+
Console.WriteLine("Error: " + e.Message); // throw error message if connection unsuccessul
51+
}
52+
Console.WriteLine("\nProgram terminated. Press any key to close the window...");
53+
Console.ReadLine();
54+
}
55+
56+
// Logic to execure NON-RESILIENT database query (no retry logic)
57+
static public void InsertNonResilient(string SQLtext, string InstanceConnectionString, bool ReadBack)
58+
{
59+
AccessDatabase(SQLtext, InstanceConnectionString, ReadBack);
60+
Console.WriteLine();
61+
}
62+
63+
// Logic to execure RESILIENT database query
64+
static public int InsertResilient(string SQLtext, string InstanceConnectionString, bool ReadBack)
65+
{
66+
bool succeeded = false;
67+
int totalNumberOfTimesToTry = 4; // how many times to retry
68+
int retryIntervalSeconds = 10; // after how many seconds
69+
70+
for (int tries = 1;
71+
tries <= totalNumberOfTimesToTry;
72+
tries++)
73+
{
74+
try
75+
{
76+
if (tries > 1)
77+
{
78+
Console.WriteLine
79+
("Transient error encountered. Will begin attempt number {0} of {1} max...",
80+
tries, totalNumberOfTimesToTry
81+
);
82+
TD.Thread.Sleep(1000 * retryIntervalSeconds);
83+
retryIntervalSeconds = Convert.ToInt32
84+
(retryIntervalSeconds * 1.5);
85+
}
86+
87+
AccessDatabase(SQLtext, InstanceConnectionString, ReadBack);
88+
succeeded = true;
89+
break;
90+
}
91+
92+
catch (QC.SqlException sqlExc)
93+
{
94+
if (TransientErrorNumbers.Contains
95+
(sqlExc.Number) == true)
96+
{
97+
Console.WriteLine("{0}: transient error.", sqlExc.Number);
98+
continue;
99+
}
100+
else
101+
{
102+
Console.WriteLine(sqlExc);
103+
succeeded = false;
104+
break;
105+
}
106+
}
107+
108+
catch (Exception Exc)
109+
{
110+
Console.WriteLine(Exc);
111+
succeeded = false;
112+
break;
113+
}
114+
}
115+
116+
if (succeeded == true)
117+
{
118+
Console.WriteLine("SUCCESS.\n");
119+
return 0;
120+
}
121+
else
122+
{
123+
Console.WriteLine("ERROR: Unable to access the database.\n");
124+
return 1;
125+
}
126+
}
127+
128+
// Connects to the database, executes query
129+
static public void AccessDatabase(string sqltext, string instance, bool read)
130+
{
131+
//throw new TestSqlException(4060); //(7654321); // Uncomment for testing.
132+
133+
using (var sqlConnection = new QC.SqlConnection
134+
(GetSqlConnectionString(instance)))
135+
{
136+
using (var dbCommand = sqlConnection.CreateCommand())
137+
{
138+
sqlConnection.Open();
139+
dbCommand.CommandText = sqltext;
140+
Console.WriteLine("Executing query: " + dbCommand.CommandText);
141+
142+
// are we reading from SQL Server, or only comitting
143+
if (read == true) // execute SQL query and read reaspons
144+
{
145+
var dataReader = dbCommand.ExecuteReader();
146+
while (dataReader.Read())
147+
{
148+
Console.WriteLine(dataReader.GetString(0));
149+
}
150+
} else // exectue SQL query and report rows affected
151+
{
152+
int rowsAffected = dbCommand.ExecuteNonQuery(); //execute query and get row count
153+
Console.WriteLine(rowsAffected + " row(s) updated");
154+
}
155+
}
156+
}
157+
}
158+
159+
// Build connection string to the server
160+
// ADD your SQL MI server details into App.config,
161+
// OR manuall edit the four string values - DataSource, InitialCatalog, UserID, Password with your SQL MI connection details
162+
static private string GetSqlConnectionString(string instance)
163+
{
164+
// Prepare the connection string to Azure SQL Database.
165+
var sqlConnectionSB = new QC.SqlConnectionStringBuilder();
166+
167+
// Change these values to your values.
168+
sqlConnectionSB.DataSource = ConfigurationManager.AppSettings.Get(instance + ".server"); // Server
169+
sqlConnectionSB.InitialCatalog = ConfigurationManager.AppSettings.Get(instance + ".database"); // Database
170+
sqlConnectionSB.UserID = ConfigurationManager.AppSettings.Get(instance + ".username");
171+
sqlConnectionSB.Password = ConfigurationManager.AppSettings.Get(instance + ".pass");
172+
173+
// Adjust these values if you like. (ADO.NET 4.5.1 or later.)
174+
sqlConnectionSB.ConnectRetryCount = 3;
175+
sqlConnectionSB.ConnectRetryInterval = 10; // Seconds.
176+
177+
// Leave these values as they are.
178+
sqlConnectionSB.IntegratedSecurity = false;
179+
sqlConnectionSB.Encrypt = true;
180+
sqlConnectionSB.ConnectTimeout = 30;
181+
182+
// Test the connection string configuration online
183+
// Console.WriteLine(sqlConnectionSB);
184+
185+
return sqlConnectionSB.ToString();
186+
}
187+
188+
// Error numbers for transient errors
189+
static public CG.List<int> TransientErrorNumbers =
190+
new CG.List<int> { 4060, 40197, 40501, 40613, 49918, 49919, 49920, 11001 };
191+
}
192+
193+
}

0 commit comments

Comments
 (0)