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.
Używaj metod strumieniowania Microsoft.Data.SqlClient do przetwarzania dużych wartości bez wcześniejszego ładowania całej wartości do pamięci aplikacji. Przesyłanie strumieniowe jest przydatne w przypadku plików binarnych, dużych tekstów, XML, JSON oraz transferu między serwerami.
Streaming nie sprawia, że wartość ma możliwość ustawiania pozycji ani nie czyni jednoczesnych operacji na czytniku bezpiecznymi. Połączenie, polecenie, czytnik, strumień źródłowy oraz obiekt docelowy muszą pozostać aktywne do zakończenia transferu.
Przykłady w tym artykule zakładają, że otwarte połączenie SqlConnection o nazwie connection jest skierowane do przykładowej bazy danych AdventureWorks.
Przykłady w języku C# wymagają using Microsoft.Data.SqlClient;. Przykłady, które używają SqlDbType lub CommandBehavior również wymagają using System.Data;.
Strumieniowanie danych z bazy SQL
Wykonaj polecenie za pomocą CommandBehavior.SequentialAccess i odczytuj kolumny według kolejności porządkowej. W dostępie sekwencyjnym, po przejściu dalej niż dana kolumna, nie czytaj wcześniejszej kolumny w tym samym wierszu.
Stosuj następujące SqlDataReader metody:
| Metoda | Result | Typowe dane SQL |
|---|---|---|
| GetStream | Stream | dane binarne, varbinary, image oraz dane typu zdefiniowanego przez użytkownika (UDT) |
| GetTextReader | TextReader | Charakterystyka i dane JSON |
| GetXmlReader | XmlReader | xml |
Wywołaj IsDBNull przed zażądaniem strumienia dla kolumny nullable. Metoda pobierająca strumieniowo używana z niekompatybilnym typem SQL zgłasza wyjątek. Odczytaj do końca lub zamknij bieżący strumień przed przeczytaniem kolejnej kolumny, przesunięciem wiersza do przodu lub przejściem do następnego wyniku.
GetStream nie jest obsługiwany dla zaszyfrowanych kolumn.
GetTextReader nie obsługuje sekwencyjnego dostępu do zaszyfrowanej kolumny.
CommandTimeout ma zastosowanie, gdy Microsoft.Data.SqlClient czeka na pakiety sieciowe podczas wykonywania i odczytu. Czas, który twoja aplikacja poświęca na przetwarzanie już otrzymanych danych, nie jest liczony. O anulowaniu i limitach czasu zobacz Programowanie asynchroniczne.
Przesyłaj strumieniowo dane binarne
AdventureWorks przechowuje zawartość plików w kolumnie varbinary(max)Production.Document.Document dopuszczającej wartość NULL. Ten przykład kopiuje jedną wartość do pliku z ograniczonym buforem:
using var command = new SqlCommand("""
SELECT TOP (1) Document
FROM Production.Document
WHERE Document IS NOT NULL
ORDER BY ModifiedDate DESC;
""", connection);
using SqlDataReader reader = command.ExecuteReader(
CommandBehavior.SequentialAccess);
if (reader.Read())
{
using Stream source = reader.GetStream(0);
using FileStream destination = File.Create("document.bin");
source.CopyTo(destination);
}
W przypadku tekstu użyj GetTextReader i skopiuj do TextWriter schowka. W przypadku XML używaj GetXmlReader i przetwarzaj węzły XML bez konwersji pełnej wartości na ciąg łańcuchowy.
Przesyłaj dane do bazy danych SQL
Ustaw Value na obiekt streamingowy i wybierz kompatybilny typ SQL:
| Typ wartości | Zgodne typy parametrów |
|---|---|
| Stream |
Binary, VarBinary, oraz starszy typ Image |
| TextReader |
Char, NChar, VarChar, NVarChar, starsze typy Text i NText, Xml, oraz Json |
| XmlReader |
Char, NChar, VarChar, NVarChar, starsze typy Text i NText, Xml oraz Json |
Ustaw Size jawnie.
Size Ogranicza przelewaną kwotę. Użyj -1 dla parametru (max), gdy chcesz wysłać kompletne źródło.
W przypadku przesyłania z ograniczoną pamięcią używaj VarBinary, VarChar lub NVarChar z Size = -1, lub używaj Xml lub Json. Microsoft.Data.SqlClient buforuje źródło do tablicy bajtów lub ciągu przed wykonaniem dla typów innych niż (max) znakowe i binarne oraz starszych typów Image, Text i NText.
Przesyłaj strumieniowo wartość parametru
Ten przykład przesyła plik przez parametr varbinary(max) i zwraca liczbę otrzymanych bajtów. Nie przechowuje wartości:
using FileStream input = File.OpenRead("document.bin");
using var command = new SqlCommand(
"SELECT DATALENGTH(@content);",
connection);
command.Parameters.Add(
new SqlParameter("@content", SqlDbType.VarBinary, -1)
{
Value = input
});
long length = (long)command.ExecuteScalar()!;
Console.WriteLine($"{length} bytes");
Zachowaj obiekt wejściowy otwarty do zakończenia wykonania polecenia. Przekaż token anulowania do asynchronicznej metody wykonania lub wywołaj Cancel, aby zażądać anulowania operacji strumieniowania. Anulowanie jest realizowane w miarę możliwości. Operacja może zakończyć się, zanim anulowanie zostanie zastosowane.
Wyjątek ze strumienia źródłowego lub czytnika powoduje błąd wykonania polecenia. Nie próbuj ponownie z tego samego obiektu, chyba że uda Ci się ustalić jego pozycję i operacja bazy danych jest bezpieczna do powtórzenia.
Przesyłaj dane z jednej bazy SQL do drugiej
Ten przykład przekazuje strumień dokumentów AdventureWorks bezpośrednio do parametru w innym otwartym elemencie SqlConnection o nazwie destinationConnection. Przykładowe polecenie podaje długość odebranych danych. Zastąp go parametryzowanym poleceniem wstawienia lub aktualizacji w docelowej bazie danych:
using var readSource = new SqlCommand("""
SELECT TOP (1) Document
FROM Production.Document
WHERE Document IS NOT NULL
ORDER BY ModifiedDate DESC;
""", connection);
using SqlDataReader sourceReader = readSource.ExecuteReader(
CommandBehavior.SequentialAccess);
if (sourceReader.Read())
{
using Stream content = sourceReader.GetStream(0);
using var write = new SqlCommand(
"SELECT DATALENGTH(@content);",
destinationConnection);
write.Parameters.Add(
new SqlParameter("@content", SqlDbType.VarBinary, -1)
{
Value = content
});
Console.WriteLine(write.ExecuteScalar());
}
Polecenia źródłowe i docelowe nie korzystają z tej samej transakcji. Jeśli twoja aplikacja wymaga skoordynowanych operacji atomowych na serwerach, zaprojektuj i przetestuj tę granicę transakcyjną osobno.