Sdílet prostřednictvím


Krok 4: Odolné připojení k SQL pomocí ADO.NET

Stáhnout 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ů:

  1. 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.
  2. Otevřete podokno Průzkumník řešení.
  3. Otevřete soubor Program.cs.
  4. Obsah souboru Program.cs zcela nahraďte kódem v následujícím bloku kódu.
  5. 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:

  1. Otevřete okno konzoly, do kterého jste zkompilovali binární RetryAdo2.exe.
  2. 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ě

  1. 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.
  2. Spusťte RetryAdo2.exea počkejte na zobrazení první přechodné chyby, pravděpodobně 11001.
  3. Znovu se připojte k síti, zatímco RetryAdo2.exe nadále běží.
  4. 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

  1. Dočasně přidejte číslo chyby 40615 do TransientErrorNumbersa znovu zkompilujte.
  2. Nastavte bod přerušení na řádku: new QC.SqlConnectionStringBuilder().
  3. 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.
  4. Opravte pravopisné chyby.
  5. Nechte program běžet a úspěšně dokončit.
  6. 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