Langkah 4: Sambungkan dengan andal ke SQL menggunakan ADO.NET

Mengunduh ADO.NET

Artikel ini menyediakan contoh kode C# yang menunjukkan logika retry yang diimplementasikan secara manual. Logika retry menangani kesalahan sementara, atau gangguan sementara, yang mungkin hilang jika program menunggu dan mencoba operasi lagi.

Important

Untuk aplikasi baru yang menggunakan Microsoft.Data.SqlClient 3.0 dan versi yang lebih baru, sebaiknya gunakan logika percobaan ulang driver yang dapat dikonfigurasi daripada mengimplementasikan perulangan percobaan ulang. Mulailah dengan Konfigurasikan logika coba ulang di SqlClient.

Sumber kesalahan sementara meliputi:

  • Kegagalan singkat jaringan yang mendukung Internet.
  • Sistem cloud mungkin sedang menyeimbangkan sumber dayanya saat kueri Anda tiba.

Kelas ADO.NET untuk menghubungkan ke SQL Server juga dapat terhubung ke Azure SQL Database. Program klien Anda dapat mengalami gangguan sementara. Ini seharusnya dapat pulih dengan menggunakan kebijakan percobaan ulang yang terbatas dan sesuai dengan operasi tersebut.

Langkah 1: Identifikasi kesalahan sementara

Program Anda harus membedakan antara kesalahan sementara dan kesalahan persisten. Kesalahan sementara adalah kondisi kesalahan yang dapat membaik dalam waktu singkat, seperti masalah jaringan sementara. Contoh kesalahan persisten adalah salah ejaan nama database target. Dalam kasus itu, error "No such database found" tetap ada dan tidak cepat hilang.

Daftar nomor kesalahan yang dikategorikan sebagai kesalahan sementara tersedia di Pesan kesalahan untuk aplikasi klien SQL Database.

Langkah 2: Membuat dan menjalankan aplikasi sampel

Sampel ini mengasumsikan .NET Framework 4.6.2 atau yang lebih baru diinstal. Contoh kode C# terdiri dari satu file bernama Program.cs. Kodenya disediakan di bagian berikutnya.

Langkah 2.a: Mengambil dan mengkompilasi sampel kode

Anda dapat mengkompilasi sampel dengan langkah-langkah berikut:

  1. Dalam edisi Visual Studio Community gratis, buat proyek baru dari templat Aplikasi Konsol C#.

    • Pilih File>New>>>Templates>Visual C#>Windows>Classic Desktop>Console Application.

    • Beri nama proyek RetryAdo2.

  2. Buka jendela Penjelajah Solusi.

    • Lihat nama proyek Anda.
    • Pada proyek Anda, tambahkan dependensi NuGet pada paket Microsoft.Data.SqlClient.
    • Lihat nama Program.cs file.
  3. Buka file Program.cs.

  4. Ganti seluruh isi Program.cs file dengan kode pada blok kode berikut.

  5. Pilih menu Build>Build Solution.

Langkah 2.b: Menyalin dan menempelkan kode sampel

Tempelkan kode ini ke file Anda Program.cs .

Kemudian, edit string untuk nama server dan kata sandi. Anda dapat menemukan string ini dalam metode bernama GetSqlConnectionString.

Nota

String koneksi tersebut ditujukan untuk Azure SQL Database, karena mencakup awalan empat karakter tcp:. Namun, Anda dapat mengatur string server untuk terhubung ke instance SQL Server Anda.

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; }
}

Langkah 2.c: Jalankan program

Berkas yang dapat dieksekusi RetryAdo2.exe tidak menerima parameter. Untuk menjalankan .exe:

  1. Buka jendela konsol di folder tempat Anda mengompilasi RetryAdo2.exe biner.
  2. Jalankan RetryAdo2.exe tanpa parameter input.
database_firewall_rules_table   245575913
filestream_tombstone_2073058421 2073058421
filetable_updates_2105058535    2105058535

Langkah 3: Cara untuk menguji logika percobaan ulang Anda

Anda dapat mensimulasikan kesalahan sementara untuk menguji logika retry Anda dengan beberapa cara.

Langkah 3.a: Membuang pengecualian pengujian

Sampel kode meliputi:

  • Kelas kedua kecil bernama TestSqlException dengan properti bernama Number.
  • //throw new TestSqlException(4060); , yang dapat Anda hapus tanda komentarnya.

Jika Anda menghapus komentar dari pernyataan throw dan mengompilasi ulang, eksekusi RetryAdo2.exe berikutnya akan menampilkan sesuatu seperti berikut.

[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\]
>>

Langkah 3.b: Coba lagi dengan kesalahan persisten

Untuk membuktikan kode menangani kesalahan persisten dengan benar, jalankan ulang tes sebelumnya. Alih-alih menggunakan nomor error transien nyata seperti 4060, gunakan angka fiksi 7654321. Program memperlakukan angka ini sebagai kesalahan persisten dan melewati setiap percobaan ulang.

Langkah 3.c: Putuskan sambungan dari jaringan

  1. Putuskan sambungan komputer klien Anda dari jaringan.
    • Untuk desktop, cabut kabel jaringan.
    • Untuk laptop, tekan kombinasi fungsi tombol untuk mematikan adaptor jaringan.
  2. Mulai RetryAdo2.exe, dan tunggu konsol menampilkan error transien pertama, kemungkinan 11001.
  3. Sambungkan kembali ke jaringan, sementara RetryAdo2.exe terus berjalan.
  4. Perhatikan konsol melaporkan keberhasilan pada percobaan ulang berikutnya.

Langkah 3.d: Salah mengeja nama server untuk sementara

  1. Tambahkan sementara 40615 sebagai nomor kesalahan lain ke TransientErrorNumbers, lalu kompilasi ulang.
  2. Atur titik henti pada baris: new QC.SqlConnectionStringBuilder().
  3. Gunakan fitur Edit dan Lanjutkan untuk sengaja salah mengeja nama server, beberapa baris di bawah ini.
    • Biarkan program berjalan dan kembali ke titik henti Anda.
    • Kesalahan 40615 terjadi.
  4. Perbaiki kesalahan ejaan.
  5. Biarkan program berjalan dan berhasil diselesaikan.
  6. Hapus 40615, dan kompilasi ulang.

Langkah selanjutnya