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 bevat een C#-codevoorbeeld dat aangepaste logica voor opnieuw proberen demonstreert. De logica voor opnieuw proberen biedt betrouwbaarheid. De logica voor opnieuw proberen is ontworpen om tijdelijke fouten of overgangsfouten die meestal verdwijnen als het programma enkele seconden wacht en opnieuw probeert.
Bronnen van tijdelijke fouten zijn:
- Een korte fout in het netwerk dat internet ondersteunt.
- Een cloudsysteem kan op het moment dat uw query werd verzonden, zijn resources balanceren.
De ADO.NET klassen voor het maken van verbinding met uw lokale Microsoft SQL Server kunnen ook verbinding maken met Azure SQL Database. De ADO.NET klassen kunnen echter niet alle robuustheid en betrouwbaarheid bieden die nodig zijn voor productiegebruik. Uw clientprogramma kan tijdelijke fouten tegenkomen waaruit het geruisloos en soepel moet herstellen en zelfstandig doorgaan.
Stap 1: Tijdelijke fouten identificeren
Uw programma moet onderscheid maken tussen tijdelijke fouten versus permanente fouten. Tijdelijke fouten zijn foutvoorwaarden die binnen een korte periode kunnen worden gewist, zoals tijdelijke netwerkproblemen. Een voorbeeld van een permanente fout zou zijn als uw programma een spelfout bevat van de naam van de doeldatabase. In dit geval blijft de fout 'Geen dergelijke database gevonden' behouden en kan deze niet binnen een korte periode worden gewist.
De lijst met foutnummers die zijn gecategoriseerd als tijdelijke fouten, is beschikbaar in foutberichten voor SQL Database-clienttoepassingen
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 met de naam 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.
- Bestand > Nieuw > Project > Geïnstalleerde > Sjablonen > Visual C# > Windows > Classic Desktop Console-toepassing >
- 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.
- Zie de naam van het Program.cs-bestand.
- Open het bestand Program.cs.
- Vervang de inhoud van het Program.cs bestand volledig door de code in het volgende codeblok.
- Selecteer het menu Build > Oplossing bouwen.
Stap 2.b: Voorbeeldcode kopiëren en plakken
Plak deze code in het Program.cs-bestand .
Vervolgens moet u de tekenreeksen bewerken voor servernaam, wachtwoord enzovoort. U vindt deze tekenreeksen in de methode GetSqlConnectionString.
Opmerking
De verbindingsreeks voor de servernaam is gericht op Azure SQL Database, omdat deze het voorvoegsel van vier tekens van tcp:bevat. U kunt de servertekenreeks echter aanpassen om verbinding te maken met uw Microsoft SQL Server.
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 uitvoerbare bestand RetryAdo2.exe heeft geen parameters nodig. De .exe uitvoeren:
- Open een consolevenster waarin u het binaire RetryAdo2.exe hebt gecompileerd.
- Voer RetryAdo2.exeuit, zonder 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
Er zijn verschillende manieren waarop u een tijdelijke fout kunt simuleren om uw logica voor opnieuw proberen te testen.
Stap 3.a: Een testonderzondering genereren
Het codevoorbeeld bevat:
- Een kleine tweede klasse met de naam TestSqlException, met een eigenschap met de naam Number.
-
//throw new TestSqlException(4060);, die je kunt decommentariëren.
Als u de opmerking bij de instructie throw verwijdert en opnieuw compileert, voert de volgende uitvoering van RetryAdo2.exe iets uit dat vergelijkbaar is 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
Als u wilt bewijzen dat de code permanente fouten correct verwerkt, voert u de voorgaande test opnieuw uit, behalve dat u het aantal echte tijdelijke fouten, zoals 4060, niet gebruikt. Gebruik in plaats daarvan het onzinnummer 7654321. Het programma moet dit behandelen als een permanente fout en moet een nieuwe poging overslaan.
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.exeen wacht totdat de console de eerste tijdelijke fout weergeeft, waarschijnlijk 11001.
- Maak opnieuw verbinding met het netwerk, terwijl RetryAdo2.exe blijft werken.
- 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 hercompileren.
- 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.