Langkah 4: Sambungkan dengan tangguh ke SQL dengan ADO.NET

Mengunduh ADO.NET

Topik ini menyediakan sampel kode C# yang menunjukkan logika coba lagi kustom. Logika coba lagi memberikan keandalan. Logika coba lagi dirancang untuk memproses kesalahan sementara atau kesalahan sementara yang cenderung hilang jika program menunggu beberapa detik dan mencoba kembali.

Sumber kesalahan sementara meliputi:

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

Kelas ADO.NET untuk menyambungkan ke Microsoft SQL Server lokal Anda juga dapat tersambung ke Azure SQL Database. Namun, dengan sendirinya kelas ADO.NET tidak dapat memberikan semua ketahanan dan keandalan yang diperlukan dalam penggunaan produksi. Program klien Anda dapat mengalami kesalahan sementara dari mana ia harus diam-diam dan dengan anggun pulih dan melanjutkan sendiri.

Langkah 1: Identifikasi kesalahan sementara

Program Anda harus membedakan antara kesalahan sementara versus kesalahan persisten. Kesalahan sementara adalah kondisi kesalahan yang dapat dihapus dalam waktu singkat, seperti masalah jaringan sementara. Contoh kesalahan persisten adalah, jika program Anda memiliki kesalahan ejaan nama database target - dalam hal ini, kesalahan "Tidak ada database yang ditemukan" akan bertahan, dan tidak memiliki peluang untuk membersihkan dalam waktu singkat.

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. Sampel 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. Di edisi Visual Studio Community gratis, buat proyek baru dari templat Aplikasi Konsol C#.
    • File > New > Project > Install > Templates > Visual C# > Windows > Classic Desktop > Console Application
    • Beri nama proyek RetryAdo2.
  2. Buka panel Penjelajah Solusi.
    • Lihat nama proyek Anda.
    • Pada proyek Anda, tambahkan dependensi NuGet pada paket Microsoft.Data.SqlClient.
    • Lihat nama file Program.cs.
  3. Membuka file Program.cs.
  4. Sepenuhnya ganti konten file Program.cs dengan kode di blok kode berikut.
  5. Klik menu Build > Build Solution.

Langkah 2.b: Salin dan tempel kode sampel

Tempelkan kode ini ke dalam file Program.cs Anda.

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

CATATAN: String koneksi untuk nama server diarahkan ke Azure SQL Database, karena menyertakan awalan empat karakter tcp:. Tetapi Anda dapat menyesuaikan string server untuk menyambungkan ke SQL Server Microsoft 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);
                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             = "MyPassword",
            // 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

InputRetryAdo2.exe yang dapat dieksekusi tidak memiliki parameter. Untuk menjalankan .exe:

  1. Buka jendela konsol tempat Anda telah mengkompilasi biner RetryAdo2.exe.
  2. Jalankan RetryAdo2.exe, tanpa parameter input.
database_firewall_rules_table   245575913  
filestream_tombstone_2073058421 2073058421  
filetable_updates_2105058535    2105058535  

Langkah 3: Cara menguji logika coba lagi Anda

Ada berbagai cara untuk mensimulasikan kesalahan sementara untuk menguji logika coba lagi Anda.

Langkah 3.a: Melemparkan pengecualian pengujian

Sampel kode meliputi:

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

Jika Anda membatalkan komentar pernyataan lemparan, dan mengkombinasikan ulang, eksekusi berikutnyaRetryAdo2.exe menghasilkan sesuatu yang mirip dengan yang berikut ini.

[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 pengujian sebelumnya kecuali jangan gunakan jumlah kesalahan sementara nyata seperti 4060. Sebagai gantinya gunakan angka omong kosong 7654321. Program harus memperlakukan ini sebagai kesalahan persisten, dan harus melewati coba lagi.

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 kesalahan sementara pertama, mungkin 11001.
  3. Sambungkan kembali ke jaringan, saat RetryAdo2.exe terus berjalan.
  4. Tonton keberhasilan laporan konsol pada percobaan ulang berikutnya.

Langkah 3.d: Salah mengeja nama server untuk sementara

  1. Tambahkan 40615 untuk sementara sebagai nomor kesalahan lain ke TransientErrorNumbers, dan 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 berikutnya

Untuk menjelajahi praktik terbaik dan pedoman desain lainnya, kunjungi Menghubungkan ke SQL Database: Tautan, Praktik Terbaik, dan Pedoman Desain