Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Verwenden Sie Microsoft. Data.SqlClient-Streaming-Methoden, um große Werte zu verarbeiten, ohne vorher den vollständigen Wert in den Anwendungsspeicher zu laden. Streaming ist nützlich für Binärdateien, große Texte, XML, JSON und Server-zu-Server-Übertragungen.
Streaming macht den Wert nicht wahlfrei zugreifbar und macht gleichzeitige Operationen auf einem Reader nicht sicher. Die Verbindung, der Befehl, der Leser, der Quellstrom und das Zielobjekt müssen bestehen bleiben, bis die Übertragung abgeschlossen ist.
Die Beispiele in diesem Artikel gehen davon aus, dass eine offene SqlConnection mit dem Namen connection die AdventureWorks-Beispieldatenbank anspricht.
Die C#-Beispiele erfordern using Microsoft.Data.SqlClient;. Beispiele, die SqlDbType oder CommandBehavior verwenden, erfordern auch using System.Data;.
Daten aus einer SQL-Datenbank streamen
Führe den Befehl mit CommandBehavior.SequentialAccess und lies die Spalten in ordinaler Reihenfolge. Bei sequentiellem Zugriff solltest du, nachdem du an einer Spalte vorbeigegangen bist, keine frühere Spalte in derselben Reihe lesen.
Verwenden Sie diese SqlDataReader Methoden:
| Methode | Ergebnis | Typische SQL-Daten |
|---|---|---|
| GetStream | Stream | binary, varbinary, image und Daten vom benutzerdefinierten Typ (UDT) |
| GetTextReader | TextReader | Zeichen- und JSON-Daten |
| GetXmlReader | XmlReader | xml |
Rufen Sie IsDBNull an, bevor Sie einen Stream für eine nullable Spalte anfordern. Ein Streaming-Getter, der mit einem inkompatiblen SQL-Typ verwendet wird, löst eine Ausnahme aus. Verbrauchen oder verwerfen Sie den aktuellen Stream, bevor Sie eine andere Spalte lesen, zur nächsten Zeile wechseln oder zum nächsten Ergebnis übergehen.
GetStream wird für verschlüsselte Spalten nicht unterstützt.
GetTextReader unterstützt keinen sequentiellen Zugriff auf eine verschlüsselte Spalte.
CommandTimeout gilt, während Microsoft.Data.SqlClient während der Ausführung und des Lesens auf Netzwerkpakete wartet. Die Zeit, die Ihre Anwendung mit der Verarbeitung bereits erhaltener Daten verbringt, wird nicht angerechnet. Für Abbruch und Zeitüberschreitungen siehe Asynchrone Programmierung.
Binärdaten streamen
AdventureWorks speichert Dateiinhalte in der NULL-zulässigen varbinary(max)Production.Document.Document Spalte. Dieses Beispiel kopiert einen Wert in eine Datei mit begrenztem Puffer:
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);
}
Verwenden Sie für Text GetTextReader und kopieren Sie es in ein TextWriter. Verwenden Sie für XML GetXmlReader und bearbeiten Sie XML-Knoten, ohne den vollständigen Wert in eine Zeichenkette umzuwandeln.
Daten in eine SQL-Datenbank streamen
Setze Value auf ein Streaming-Objekt und wähle einen kompatiblen SQL-Typ:
| Werttyp | Kompatible Parametertypen |
|---|---|
| Stream |
Binary, VarBinary und der Legacy-Image-Typ |
| TextReader |
Char, Text, NText, Xml, die Legacy-Typen NVarChar und VarChar, NChar und Json |
| XmlReader |
Char, Text, NText, Xml, die Legacytypen NVarChar und VarChar, NChar und Json |
Legen Sie Size explizit fest.
Size begrenzt den überwiesenen Betrag. Verwenden Sie -1 für einen (max)-Parameter, wenn Sie die vollständige Quelle senden möchten.
Für den Transfer mit beschränktem Speicher verwenden Sie VarBinary, VarChar oder NVarChar mit Size = -1, oder verwenden Sie Xml oder Json. Microsoft.Data.SqlClient puffert die Quelldaten vor der Ausführung in ein Byte-Array oder einen String für Nicht-(max)Zeichen- und Binärtypen sowie für die Legacy-Image-, Text- und NText-Typen.
Parameterwert streamen
Dieses Beispiel sendet eine Datei über einen varbinary(max)-Parameter und gibt die Anzahl der empfangenen Bytes zurück. Der Wert wird nicht gespeichert:
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");
Lassen Sie das Eingabeobjekt offen, bis die Befehlsausführung abgeschlossen ist. Geben Sie ein Abbruchtoken an eine asynchrone Ausführungsmethode weiter, oder rufen Sie Cancel auf, um den Abbruch der Streaming-Operation anzufordern. Stornierung erfolgt nach bestem Bemühen. Die Operation könnte abgeschlossen werden, bevor der Abbruch wirksam wird.
Eine Ausnahme aus dem Quellstream oder ein Leserfehler führt zu einem Fehler bei der Befehlsausführung. Versuche es nicht erneut mit demselben Objekt, es sei denn, du kannst seine Position bestimmen und die Datenbankoperation kann sicher wiederholt werden.
Daten von einer SQL-Datenbank in eine andere streamen
Dieses Beispiel übergibt einen AdventureWorks-Dokumentstrom direkt an einen Parameter in einem anderen geöffneten SqlConnection namens destinationConnection. Der Musterbefehl gibt die empfangene Länge an. Ersetzen Sie ihn durch den parametrisierten Ein- oder Aktualisierungsbefehl der Zieldatenbank:
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());
}
Die Quell- und Zielbefehle teilen sich keine Transaktion. Wenn Ihre Anwendung koordinierte atomare Arbeit über Server hinweg erfordert, entwerfen und testen Sie diese Transaktionsgrenze separat.