Stöd för SqlClient-strömning

Använd Microsoft. Data.SqlClient-strömningsmetoder för att bearbeta stora värden utan att först ladda hela värdet i applikationsminnet. Streaming är användbart för binära filer, stor text, XML, JSON och server-till-server-överföring.

Streaming gör inte värdet sökbart eller gör samtidiga operationer på en läsare säkra. Anslutningen, kommandot, läsaren, källströmmen och destinationsobjektet måste förbli vid liv tills överföringen är klar.

I exemplen i den här artikeln förutsätts att en öppen SqlConnection med namnet connection riktar sig mot AdventureWorks-exempeldatabasen.

C#-exemplen kräver using Microsoft.Data.SqlClient;. Exempel som också använder SqlDbType eller CommandBehavior kräver using System.Data;.

Strömma data från en SQL-databas

Utför kommandot med CommandBehavior.SequentialAccess och läs kolumnerna i ordinal ordning. Med sekventiell åtkomst, efter att du gått förbi en kolumn, läs inte en tidigare kolumn i samma rad.

Använd dessa SqlDataReader metoder:

Method Result Typisk SQL-data
GetStream Stream binary, varbinary, image och data av användardefinierad typ (UDT)
GetTextReader TextReader Tecken- och JSON-data
GetXmlReader XmlReader xml

Ring IsDBNull innan du begär en stream för en nullbar kolumn. En streaming-getter som används med en inkompatibel SQL-typ kastar. Konsumera eller kassera den aktuella strömmen innan du läser en annan kolumn, avancerar raden eller går vidare till nästa resultat.

GetStream stöds inte för krypterade kolumner. GetTextReader stöder inte sekventiell åtkomst till en krypterad kolumn.

CommandTimeout gäller medan Microsoft.Data.SqlClient väntar på nätverkspaket under körning och läsning. Tiden som din applikation lägger på att bearbeta redan mottagen data räknas inte. För avbokning och timeouts, se Asynkron programmering.

Strömma binärdata

AdventureWorks lagrar filinnehåll i den nullbara varbinary(max)Production.Document.Document-kolumnen. Detta exempel kopierar ett värde till en fil med en begränsad buffert:

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

För text, använd GetTextReader och kopiera till en TextWriter. För XML, använd GetXmlReader och bearbeta XML-noder utan att konvertera hela värdet till sträng.

Skicka data till en SQL-databas

Ställ Value in på ett strömmande objekt och välj en kompatibel SQL-typ:

Värdetyp Kompatibla parametertyper
Stream Binary, VarBinary, och den äldre Image typen
TextReader Char, Text, NText, Xml, de äldre NVarChar- och VarChar-typerna, NChar, och Json
XmlReader Char, Text, NText, Xml, de äldre NVarChar- och VarChar-typerna, NChar och Json

Ange Size explicit. Size begränsar det överförda beloppet. Använd -1 för en (max)-parameter när du vill skicka hela källan.

För minnesbegränsad överföring, använd VarBinary, VarChar, eller NVarChar med Size = -1, eller använd Xml eller Json. Microsoft.Data.SqlClient buffrar källan till en bytearray eller sträng innan exekvering för teckentyper som inte är (max) och binära typer samt de äldre Image, Text och NText-typerna.

Strömma ett parametervärde

Detta exempel skickar en fil via en parameter av typen varbinary(max) och returnerar antalet mottagna byte. Den lagrar inte värdet:

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");

Håll indataobjektet öppet tills kommandoexekveringen är klar. Skicka en avbokningstoken till en asynkron exekveringsmetod eller anrop Cancel för att begära avbokning av strömningsoperationen. Avbokning sker i mån av möjlighet. Operationen kan avslutas innan avbrytningen träder i kraft.

Ett undantag från källströmmen eller läsaren gör att kommandokörningen misslyckas. Försök inte igen från samma objekt om du inte kan fastställa dess position eller om databasoperationen inte är säker att upprepa.

Strömma data från en SQL-databas till en annan

Detta exempel skickar en AdventureWorks-dokumentström direkt till en parameter på en annan öppen SqlConnection med namnet destinationConnection. Exempelkommandot rapporterar den mottagna längden. Ersätt det med destinationsdatabasens parameteriserade insert- eller uppdateringskommando:

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

Käll- och destinationskommandona delar inte en transaktion. Om din applikation kräver koordinerat atomärt arbete över servrar, designa och testa den transaktionsgränsen separat.