Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Dit artikel biedt een voorbeeld van C#-code dat handmatig geïmplementeerde hertry-logica demonstreert. De herkansingslogica behandelt tijdelijke fouten, of tijdelijke fouten, die kunnen verdwijnen als het programma wacht en de operatie opnieuw probeert.
Belangrijk
Voor nieuwe applicaties die Microsoft gebruiken. Data.SqlClient 3.0 en latere versies geven de voorkeur aan de configureerbare retry-logica van de driver in plaats van het implementeren van een retry-lus. Begin met het configureren van logica voor opnieuw proberen in SqlClient.
Bronnen van tijdelijke fouten zijn:
- Een korte storing van het netwerk dat het internet ondersteunt.
- Een cloudsysteem is mogelijk bezig zijn resources te verdelen wanneer je query binnenkomt.
De ADONET-klassen voor verbinding met SQL Server kunnen ook verbinding maken met Azure SQL Database. Je clientprogramma kan tijdelijke storingen tegenkomen. Het zou moeten herstellen door gebruik te maken van een begrensd herprobeerbeleid dat geschikt is voor de operatie.
Stap 1: Tijdelijke fouten identificeren
Je programma moet onderscheid maken tussen tijdelijke fouten en persistente fouten. Tijdelijke fouten zijn fouten die in korte tijd kunnen verdwijnen, zoals tijdelijke netwerkproblemen. Een voorbeeld van een persistente fout is een spelfout van de naam van de doeldatabase. In dat geval blijft de fout "No such database found" aanwezig en verdwijnt niet snel.
De lijst met foutnummers die als tijdelijke fouten zijn gecategoriseerd, is beschikbaar bij Foutmeldingen voor SQL Database-clientapplicaties.
Stap 2: Voorbeeldtoepassing maken en uitvoeren
In dit voorbeeld wordt ervan uitgegaan dat .NET Framework 4.6.2 of hoger is geïnstalleerd. Het C#-codevoorbeeld bestaat uit één bestand genaamd Program.cs. De code wordt weergegeven in de volgende sectie.
Stap 2.a: Het codevoorbeeld vastleggen en compileren
U kunt het voorbeeld compileren met de volgende stappen:
Maak in de gratis Visual Studio Community-editie een nieuw project op basis van de C#-consoletoepassingssjabloon.
Selecteer Bestand>Nieuw>>>Sjablonen>Visual C#>Windows>Klassiek bureaublad>Consoletoepassing.
Geef het project de naam
RetryAdo2.
Open het deelvenster Solution Explorer.
- Bekijk de naam van uw project.
- Voeg in uw project een NuGet-afhankelijkheid toe aan het Microsoft.Data.SqlClient-pakket.
- Bekijk de naam van het
Program.csbestand.
Open het
Program.csbestand.Vervang de volledige inhoud van het
Program.csbestand door de code in het volgende codeblok.Selecteer het menu Build>Build Solution.
Stap 2.b: Voorbeeldcode kopiëren en plakken
Plak deze code in je Program.cs bestand.
Bewerk vervolgens de strings voor de servernaam en het wachtwoord. Je kunt deze strings vinden in de methode genaamd GetSqlConnectionString.
Opmerking
De verbindingsreeks is gericht op Azure SQL Database, omdat deze het vier-teken-prefix tcp:bevat. Maar je kunt de serverstring aanpassen om verbinding te maken met je SQL Server-instantie.
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);
break;
}
catch (TestSqlException sqlExc) {
if (TransientErrorNumbers.Contains(sqlExc.Number))
{
Console.WriteLine("{0}: transient occurred. (TESTING.)", sqlExc.Number);
continue;
}
Console.WriteLine(sqlExc);
break;
}
catch (Exception e)
{
Console.WriteLine(e);
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>
/// Edit the four string values in accordance with your environment.
/// </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; }
}
Stap 2.c: Het programma uitvoeren
Het RetryAdo2.exe uitvoerbare bestand neemt geen parameters aan. Om de .exe uit te voeren:
- Open een consolevenster in de map waar je de
RetryAdo2.exebinary hebt gecompileerd. - Draai
RetryAdo2.exezonder invoerparameters.
database_firewall_rules_table 245575913
filestream_tombstone_2073058421 2073058421
filetable_updates_2105058535 2105058535
Stap 3: Manieren om uw logica voor opnieuw proberen te testen
Je kunt een tijdelijke fout simuleren om je herpogingslogica op verschillende manieren te testen.
Stap 3.a: Een testonderzondering genereren
Het codevoorbeeld bevat:
- Een kleine tweede klasse genaamd
TestSqlExceptionmet een eigenschap genaamdNumber. -
//throw new TestSqlException(4060);, die je kunt decommentariëren.
Als je de throw-instructie uit commentaar haalt en opnieuw compileert, wordt bij de volgende uitvoering van RetryAdo2.exe iets uitgevoerd dat ongeveer overeenkomt met het volgende.
[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\]
>>
Stap 3.b: Test opnieuw met een permanente fout
Om te bewijzen dat de code persistente fouten correct verwerkt, voer je de voorgaande test opnieuw uit. In plaats van een echt voorbijgaand foutgetal zoals 4060 te gebruiken, gebruik je het fictieve getal 7654321. Het programma behandelt dit getal als een persistente fout en omzeilt elke herkansing.
Stap 3.c: Verbinding met het netwerk verbreken
- Verbreek de verbinding met uw clientcomputer met het netwerk.
- Voor een desktop koppelt u de netwerkkabel los.
- Voor laptops drukt u op de functietoetscombinatie om de netwerkadapter uit te schakelen.
- Start
RetryAdo2.exe, en wacht tot de console de eerste tijdelijke foutmelding geeft, waarschijnlijk 11001. - Maak opnieuw verbinding met het netwerk, terwijl
RetryAdo2.exeactief blijft. - Bekijk het consolerapport dat succes meldt bij een volgende herhaling.
Stap 3.d: De servernaam tijdelijk verkeerd gespeld
- Voeg tijdelijk 40615 toe als een ander foutnummer aan
TransientErrorNumbers, en compilier opnieuw. - Stel een onderbrekingspunt in op de regel:
new QC.SqlConnectionStringBuilder(). - Gebruik de functie Bewerken en Doorgaan om opzettelijk de servernaam verkeerd te spellen, een paar regels hieronder.
- Laat het programma draaien en keer terug naar uw onderbrekingspunt.
- De fout 40615 treedt op.
- Corrigeer de spelfout.
- Laat het programma uitvoeren en met succes voltooien.
- Verwijder 40615 en compileer opnieuw.