Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
SqlConnectionoznacza jedno logiczne połączenie z SQL Server, Azure SQL lub innym obsługiwanym punktem końcowym kompatybilnym z SQL Server. Podczas otwierania obiektu uzyskiwane jest fizyczne połączenie z puli połączeń, jeśli jest ono dostępne. Zamknięcie lub utylizacja przywraca to fizyczne połączenie z pulą.
Używaj obiektów krótkotrwałych SqlConnection jako jednostek pracy. Nie trzymaj jednego globalnego połączenia otwartego dla aplikacji.
Buduj konfigurację połączenia
Załadować parametry połączenia z systemu konfiguracji aplikacji. Użyj, SqlConnectionStringBuilder gdy kod wymaga weryfikacji lub dodania ustawień:
string configuredConnectionString =
configuration.GetConnectionString("Orders")
?? throw new InvalidOperationException(
"Connection string 'Orders' wasn't configured.");
var builder = new SqlConnectionStringBuilder(configuredConnectionString)
{
ApplicationName = "Orders.Api",
};
Utwórz SqlConnection z builder.ConnectionString. Nie doklejaj danych wejściowych użytkownika do ciągu znaków. Informacje o wzorcach uwierzytelniania, bezpiecznym przechowywaniu i składni można znaleźć w temacie Parametry połączenia.
Otwieraj i usuwaj połączenia
Wywołaj Open w kodzie synchronicznym lub OpenAsync w kodzie asynchronicznym. Otwórz nowe logiczne połączenie dla każdej niezależnej operacji:
public static async Task<string?> LoadOrderStatusAsync(
string connectionString,
int orderId,
CancellationToken cancellationToken)
{
await using var connection = new SqlConnection(connectionString);
await connection.OpenAsync(cancellationToken);
const string sql = """
SELECT Status
FROM Sales.Orders
WHERE OrderId = @orderId;
""";
using var command =
new SqlCommand(sql, connection) { CommandTimeout = 30 };
command.Parameters.Add(
new SqlParameter("@orderId", SqlDbType.Int) { Value = orderId });
object? value =
await command.ExecuteScalarAsync(cancellationToken);
return value is null or DBNull ? null : (string)value;
}
Instrukcja await using zamyka połączenie w przypadku powodzenia, błędu lub anulowania. Po włączeniu poolingu utylizacja zwykle resetuje się i przywraca fizyczne połączenie zamiast zamykać gniazdo sieciowe.
Pozbądź się czytników i poleceń przed połączeniem, które je posiada. Nie polegaj na garbage collection ani finalizatorze, by przywrócić połączenia do puli.
Używanie asynchronicznych interfejsów API
Używaj wywołań asynchronicznych do pracy z bazą danych sieciowych na serwerach WWW, usługach, interfejsach użytkownika i pracownikach:
OpenAsync(cancellationToken)ExecuteNonQueryAsync(cancellationToken)ExecuteReaderAsync(cancellationToken)ExecuteScalarAsync(cancellationToken)ReadAsync(cancellationToken)
Nie potrzebujesz Asynchronous Processing=true. Microsoft. Data.SqlClient 4.0 i nowsze wersje nie obsługują tego słowa kluczowego parametry połączenia.
Nie rozpoczynaj kolejnej operacji na połączeniu, poleceniu lub czytniku przed zakończeniem bieżącej operacji asynchronicznej.
Zastosuj anulowanie i limity czasu
Przekaż sygnały CancellationToken dzwoniącego przez każde asynchroniczne wywołanie bazy danych. Anulowanie wymaga od dostawcy przerwania oczekujących prac, ale zakończenie nie jest gwarantowane natychmiastowe. Kontynuuj stosowanie ograniczonych limitów czasu połączeń i poleceń.
Te sterowanie ma osobne zakresy:
| Kontrola | Scope |
|---|---|
Connect Timeout |
Nawiązanie połączenia lub oczekiwanie na połączenie w grupie |
SqlCommand.CommandTimeout |
Wykonanie jednego polecenia |
CancellationToken |
Anulowanie operacji asynchronicznej na żądanie dzwoniącego |
Przekroczenie limitu czasu lub anulowanie nie oznacza, że serwer cofnął operację. Używaj transakcji, gdy wiele zmian musi zostać zatwierdzonych lub wycofanych jako jedna całość, a decyzje o ponowieniu podejmuj na podstawie idempotencji operacji i wyniku transakcji.
Zrozum stan połączenia
Właściwość State zwraca migawkę z wyliczenia ConnectionState.
| State | Meaning |
|---|---|
Closed |
Logiczne połączenie nie jest otwarte. |
Connecting |
Trwa otwarta operacja. |
Open |
Logiczne połączenie jest otwarte. |
Nie używaj State do kontroli stanu przed wykonaniem każdego polecenia. Sieć może ulec awarii po każdym sprawdzeniu. Wykonaj operację i obsługuj powstały wyjątek.
Sterownik zazwyczaj zgłasza przejścia ze stanu zamkniętego na otwarty oraz ze stanu otwartego na zamknięty. Nie polegaj na obserwacji Executing, Fetching, ani Broken jako faz cyklu życia aplikacji.
Zdarzenie StateChange zgłasza przejścia stanów. Wydarzenie InfoMessage zgłasza komunikaty informacyjne i ostrzeżenia serwera, które nie są wyjątkami. Używaj tych zdarzeń do diagnostyki, a nie do koordynacji równoległej pracy.
Nie udostępniaj połączenia jednocześnie
SqlConnection, SqlCommand, SqlDataReader, oraz SqlTransaction nie obsługują jednoczesnego użycia przez wiele wątków. Przypisz każdej współbieżnej operacji własne połączenie i pozwól, aby pula połączeń ponownie wykorzystywała połączenia fizyczne.
Multiple Active Result Sets (MARS) pozwala na wiele aktywnych partii na jednym połączeniu w obsługiwanych scenariuszach. Nie czyni obiektów SqlClient bezpiecznymi wątkowo, a dodatkowo dodaje reguły sesji i transakcji. Zostaw wyłączone, chyba że jedna operacja tego wymaga wprost.
Nie rejestruj otwartego SqlConnection jako singletona w wstrzyknięciu zależności. Zarejestruj parametry połączenia, niezmienny obiekt opcji lub fabrykę tworzącą nowe połączenie.
Używaj transakcji celowo
Transakcja lokalna jest przypisana do swojego połączenia. Każde polecenie w transakcji musi korzystać z tego połączenia i ustawić jego właściwość Transaction.
await using var connection = new SqlConnection(connectionString);
await connection.OpenAsync(cancellationToken);
await using SqlTransaction transaction =
(SqlTransaction)await connection.BeginTransactionAsync(cancellationToken);
using var command = new SqlCommand(sql, connection, transaction);
command.Parameters.Add(
new SqlParameter("@value", SqlDbType.Int) { Value = value });
await command.ExecuteNonQueryAsync(cancellationToken);
await transaction.CommitAsync(cancellationToken);
Jeśli operacja nie powiedzie się przed CommitAsync, zamknięcie transakcji spowoduje jej wycofanie. Utrzymuj transakcje krótkie. Nie wykonuj wywołań sieciowych, interakcji z użytkownikami ani nie wykonuj niezwiązanych obliczeń, gdy transakcja w bazie danych jest zablokowana.
Gdy System.Transactions.Transaction.Current jest aktywne, Open i OpenAsync są domyślnie automatycznie rejestrowane. Ustaw Enlist=false tylko wtedy, gdy operacja musi być wykonywana poza transakcją nadrzędną.
Zmierz jedno połączenie logiczne
Ustaw StatisticsEnabled na true, aby zbierać statystyki dostawcy dla jednego obiektu SqlConnection:
await using var connection = new SqlConnection(connectionString)
{
StatisticsEnabled = true,
};
await connection.OpenAsync(cancellationToken);
connection.ResetStatistics();
using var command = new SqlCommand(sql, connection);
await command.ExecuteNonQueryAsync(cancellationToken);
System.Collections.IDictionary statistics =
connection.RetrieveStatistics();
long roundTrips =
Convert.ToInt64(statistics["ServerRoundtrips"]);
RetrieveStatistics zwraca zrzut.
ResetStatistics rozpoczyna się nowa granica pomiarowa. Ustaw StatisticsEnabled=false na zatrzymanie zbierania; dotychczas zebrane wartości pozostają dostępne. Statystyki dotyczą poszczególnych obiektów połączenia i powodują dodatkowy narzut, więc włączaj je tylko na potrzeby ukierunkowanej diagnostyki, a nie dla każdego żądania produkcyjnego.
Do pomiarów puli i połączeń w całym procesie używaj liczników diagnostycznych SqlClient.
Obsługa błędów połączeń
Złap SqlException na granicy, która może zarejestrować, przetłumaczyć lub ponownie spróbować niepowodzenia. Rekord:
NumberStateClassClientConnectionId- Nazwa operacji oraz skonfigurowane identyfikatory serwera i bazy danych
Nie rejestruj w dzienniku parametrów połączenia, hasła, wpisu tajnego klienta ani tokenu dostępu.
Pozbądź się zerwanego połączenia. Pula usuwa nieprawidłowe połączenia fizyczne, gdy je wykryje. Jeśli dane uwierzytelniające, token, certyfikat, cel DNS lub serwer się zmieniły, popraw konfigurację przed ponowną próbą.
Stosuj logikę ograniczonej liczby ponowień tylko w przypadku błędów przejściowych. Ponowna próba początkowego otwarcia, odzyskiwanie bezczynnego połączenia oraz ponawianie polecenia to różne mechanizmy. Zobacz Konfigurowalna logika powtórek.