Krok 4: Odolné připojení k SQL pomocí ADO.NET
- Předchozí článek: Krok 3: Testování konceptu připojení k SQL pomocí ADO.NET
Toto téma obsahuje ukázku kódu jazyka C#, která demonstruje vlastní logiku opakování. Logika opakování poskytuje spolehlivost. Logika opakování je navržená tak, aby elegantně zvládala dočasné chyby nebo přechodné chyby, které mají tendenci mizet, pokud program počká několik sekund a opakuje to.
Mezi zdroje přechodných chyb patří:
- Stručné selhání sítí, které podporují internet.
- V době, kdy byl váš dotaz odeslán, mohl cloudový systém vyrovnávat zatížení svých prostředků.
Třídy ADO.NET pro připojení k místnímu Microsoft SQL Serveru se také můžou připojit ke službě Azure SQL Database. Samotné třídy ADO.NET však nemohou poskytovat veškerou odolnost a spolehlivost potřebnou k použití v produkčním prostředí. Váš klientský program může narazit na přechodné chyby, ze kterých by se měl tiše a elegantně zotavit a pokračovat samostatně.
Krok 1: Identifikace přechodných chyb
Program musí rozlišovat mezi přechodnými chybami a trvalými chybami. Přechodné chyby jsou chybové stavy, které se můžou během krátkého časového období vymazat, jako jsou přechodné problémy se sítí. Příkladem trvalé chyby by bylo, pokud má váš program chybně napsaný název cílové databáze – v tomto případě by se chyba "Žádná taková databáze nenalezla", která by trvala a nemá žádnou šanci vymazat během krátkého časového období.
Seznam chybových čísel, která jsou zařazena do kategorií jako přechodné chyby, je k dispozici v Chybové zprávy pro klientské aplikace SQL Database
Krok 2: Vytvoření a spuštění ukázkové aplikace
Tato ukázka předpokládá instalaci rozhraní .NET Framework 4.6.2 nebo novější. Ukázka kódu jazyka C# se skládá z jednoho souboru s názvem Program.cs. Jeho kód je k dispozici v další části.
Krok 2.a: Zachycení a kompilace ukázky kódu
Ukázku můžete zkompilovat pomocí následujících kroků:
- V bezplatné edici Visual Studio Communityvytvořte nový projekt ze šablony konzolové aplikace jazyka C#.
- > Nový > Projekt > Nainstalované šablony >> Visual C# > Windows > Klasické desktopové > Konzolová aplikace
- Pojmenujte projekt RetryAdo2.
- Otevřete podokno Průzkumník řešení.
- Podívejte se na název projektu.
- V projektu přidejte balíček Microsoft.Data.SqlClient jako závislost NuGet.
- Podívejte se na název souboru Program.cs.
- Otevřete soubor Program.cs.
- Obsah souboru Program.cs zcela nahraďte kódem v následujícím bloku kódu.
- Klikněte na nabídku Sestavit >: Sestavit řešení.
Krok 2.b: Kopírování a vložení ukázkového kódu
Vložte tento kód do souboru Program.cs.
Potom musíte upravit názvy serveru, hesla a podobně. Tyto řetězce najdete v metodě s názvem GetSqlConnectionString.
Poznámka
Připojovací řetězec pro název serveru je zaměřený na Azure SQL Database, protože obsahuje čtyřznakovou předponu tcp:. Můžete ale upravit řetězec serveru tak, aby se připojil k Microsoft SQL Serveru.
using System;
using System.Collections.Generic;
using Microsoft.Data.SqlClient;
using System.Threading;
namespace RetryAdo2;
public class Program
{
public static int Main(string[] args)
{
bool succeeded = false;
const int totalNumberOfTimesToTry = 4;
int retryIntervalSeconds = 10;
for (int tries = 1; tries <= totalNumberOfTimesToTry; tries++)
{
try
{
if (tries > 1)
{
Console.WriteLine(
"Transient error encountered. Will begin attempt number {0} of {1} max...",
tries,
totalNumberOfTimesToTry
);
Thread.Sleep(1000 * retryIntervalSeconds);
retryIntervalSeconds = Convert.ToInt32(retryIntervalSeconds * 1.5);
}
AccessDatabase();
succeeded = true;
break;
}
catch (SqlException sqlExc) {
if (TransientErrorNumbers.Contains(sqlExc.Number))
{
Console.WriteLine("{0}: transient occurred.", sqlExc.Number);
continue;
}
Console.WriteLine(sqlExc);
succeeded = false;
break;
}
catch (TestSqlException sqlExc) {
if (TransientErrorNumbers.Contains(sqlExc.Number))
{
Console.WriteLine("{0}: transient occurred. (TESTING.)", sqlExc.Number);
continue;
}
Console.WriteLine(sqlExc);
succeeded = false;
break;
}
catch (Exception e)
{
Console.WriteLine(e);
succeeded = false;
break;
}
}
if (!succeeded) {
Console.WriteLine("ERROR: Unable to access the database!");
return 1;
}
return 0;
}
/// <summary>
/// Connects to the database, reads,
/// prints results to the console.
/// </summary>
static void AccessDatabase() {
//throw new TestSqlException(4060); //(7654321); // Uncomment for testing.
using var sqlConnection = new SqlConnection(GetSqlConnectionString());
using var dbCommand = sqlConnection.CreateCommand();
dbCommand.CommandText =
@"
SELECT TOP 3
ob.name,
CAST(ob.object_id as nvarchar(32)) as [object_id]
FROM sys.objects as ob
WHERE ob.type='IT'
ORDER BY ob.name;";
sqlConnection.Open();
var dataReader = dbCommand.ExecuteReader();
while (dataReader.Read())
{
Console.WriteLine(
"{0}\t{1}",
dataReader.GetString(0),
dataReader.GetString(1)
);
}
}
/// <summary>
/// You must edit the four 'my' string values.
/// </summary>
/// <returns>An ADO.NET connection string.</returns>
static private string GetSqlConnectionString()
{
// Prepare the connection string to Azure SQL Database.
var sqlConnectionSB = new SqlConnectionStringBuilder
{
// Change these values to your values.
DataSource = "tcp:myazuresqldbserver.database.windows.net,1433", //["Server"]
InitialCatalog = "MyDatabase", //["Database"]
UserID = "MyLogin", // "@yourservername" as suffix sometimes.
Password = "<password>",
// Adjust these values if you like. (ADO.NET 4.5.1 or later.)
ConnectRetryCount = 3,
ConnectRetryInterval = 10, // Seconds.
// Leave these values as they are.
IntegratedSecurity = false,
Encrypt = true,
ConnectTimeout = 30
};
return sqlConnectionSB.ToString();
}
static List<int> TransientErrorNumbers = new()
{
4060, 40197, 40501, 40613, 49918, 49919, 49920, 11001
};
}
/// <summary>
/// For testing retry logic, you can have method
/// AccessDatabase start by throwing a new
/// TestSqlException with a Number that does
/// or does not match a transient error number
/// present in TransientErrorNumbers.
/// </summary>
internal class TestSqlException : ApplicationException
{
internal TestSqlException(int testErrorNumber)
{
Number = testErrorNumber;
}
internal int Number { get; set; }
}
Krok 2.c: Spuštění programu
Výkonné vstupy RetryAdo2.exe nevyžadují žádné parametry. Spustit .exe:
- Otevřete okno konzoly, do kterého jste zkompilovali binární RetryAdo2.exe.
- Spusťte RetryAdo2.exebez vstupních parametrů.
database_firewall_rules_table 245575913
filestream_tombstone_2073058421 2073058421
filetable_updates_2105058535 2105058535
Krok 3: Způsoby testování logiky opakování
Existuje celá řada způsobů, jak simulovat přechodnou chybu pro otestování logiky opakování.
Krok 3.a: Vyvolání testovací výjimky
Ukázka kódu zahrnuje:
- Malá druhá třída s názvem TestSqlExceptions vlastností s názvem Number.
-
//throw new TestSqlException(4060);
, které můžete odkomentovat.
Pokud odkomentujete příkaz throw a rekompilujete, další spuštění RetryAdo2.exe zobrazí výstup podobný následujícímu.
[C:\VS15\RetryAdo2\RetryAdo2\bin\Debug\]
>> RetryAdo2.exe
4060: transient occurred. (TESTING.)
Transient error encountered. Will begin attempt number 2 of 4 max...
4060: transient occurred. (TESTING.)
Transient error encountered. Will begin attempt number 3 of 4 max...
4060: transient occurred. (TESTING.)
Transient error encountered. Will begin attempt number 4 of 4 max...
4060: transient occurred. (TESTING.)
ERROR: Unable to access the database!
[C:\VS15\RetryAdo2\RetryAdo2\bin\Debug\]
>>
Krok 3.b: Opětovné otestování s trvalou chybou
Pokud chcete prokázat, že kód zpracovává trvalé chyby správně, spusťte předchozí test znovu s výjimkou nepoužívat počet skutečných přechodných chyb, jako je 4060. Místo toho použijte nesmyslné číslo 7654321. Program by s ním měl zacházet jako s trvalou chybou a měl by obejít všechny opakování.
Krok 3.c: Odpojení od sítě
- Odpojte klientský počítač od sítě.
- Pro stolní počítač odpojte síťový kabel.
- U přenosného počítače stisknutím kombinace kláves vypněte síťový adaptér.
- Spusťte RetryAdo2.exea počkejte na zobrazení první přechodné chyby, pravděpodobně 11001.
- Znovu se připojte k síti, zatímco RetryAdo2.exe nadále běží.
- Sledujte úspěšnou zprávu konzole při následném pokusu o opakování.
Krok 3.d: Dočasně chybně napsaný název serveru
- Dočasně přidejte číslo chyby 40615 do TransientErrorNumbersa znovu zkompilujte.
- Nastavte bod přerušení na řádku:
new QC.SqlConnectionStringBuilder()
. - Pomocí funkce Upravit a pokračovat úmyslně chybně zadejte název serveru, několik řádků níže.
- Nechte program spustit a vraťte se k bodu přerušení.
- Dojde k chybě 40615.
- Opravte pravopisné chyby.
- Nechte program běžet a úspěšně dokončit.
- Odeberte 40615 a rekompilujte.
Další kroky
Další osvědčené postupy a pokyny pro návrh najdete v tématu Připojení ke službě SQL Database: Odkazy, osvědčené postupy a pokyny pro návrh