Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Use os métodos de streaming do Microsoft.Data.SqlClient para processar valores grandes sem antes carregar o valor completo na memória do aplicativo. O streaming é útil para arquivos binários, texto grande, XML, JSON e transferência de servidor para servidor.
O streaming não torna o valor passível de busca nem garante que operações simultâneas em um leitor sejam seguras. A conexão, comando, leitor, fluxo de origem e objeto de destino devem permanecer ativos até o término da transferência.
Os exemplos deste artigo assumem que uma conexão connection aberta chamada SqlConnection tem como alvo o banco de dados de exemplo AdventureWorks.
Os exemplos de C# requerem using Microsoft.Data.SqlClient;. Exemplos que usam SqlDbType ou CommandBehavior também exigem using System.Data;.
Transmitir dados de um banco de dados SQL
Execute o comando com CommandBehavior.SequentialAccess e leia as colunas em ordem ordinal. Com acesso sequencial, depois de avançar além de uma coluna, não leia uma coluna anterior na mesma linha.
Use esses métodos de SqlDataReader:
| Método | Resultado | Dados SQL típicos |
|---|---|---|
| GetStream | Stream | binary, varbinary, image e dados de tipo definido pelo usuário (UDT) |
| GetTextReader | TextReader | Dados de caractere e JSON |
| GetXmlReader | XmlReader | xml |
Chame IsDBNull antes de solicitar um stream para uma coluna anulável. Um getter de streaming usado com um tipo SQL incompatível lança uma exceção. Consuma ou descarte o fluxo atual antes de ler outra coluna, avançar a linha ou passar para o próximo resultado.
GetStream não oferece suporte a colunas criptografadas.
GetTextReader não suporta acesso sequencial a uma coluna criptografada.
CommandTimeoutaplica-se enquanto Microsoft.Data.SqlClient aguarda os pacotes de rede durante a execução e leitura. O tempo que sua aplicação gasta processando dados já recebidos não é contabilizado. Para cancelamento e timeouts, veja Programação assíncrona.
Transmitir dados binários
O AdventureWorks armazena o conteúdo do arquivo na coluna anulável varbinary(max)Production.Document.Document. Este exemplo copia um valor para um arquivo com um buffer limitado:
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);
}
Para texto, use GetTextReader e copie para um TextWriter. Para XML, use GetXmlReader e processe nós XML sem converter o valor completo em string.
Transmitir dados para um banco de dados SQL
Defina Value para um objeto de streaming e escolha um tipo de SQL compatível:
| Tipo de valor | Tipos de parâmetros compatíveis |
|---|---|
| Stream |
Binary, VarBinary, e o tipo legado Image |
| TextReader |
Char, NChar, VarChar, NVarChar, os tipos legados Text e NText, Xml e Json |
| XmlReader |
Char, NChar, VarChar, NVarChar, os tipos legados Text e NText, Xml e Json |
Defina Size explicitamente.
Size limita a quantia transferida. Use -1 para um parâmetro (max) quando quiser enviar o código-fonte completo.
Para transferência de memória limitada, use VarBinary, VarChar, ou NVarChar com Size = -1, ou use Xml ou Json. Microsoft.Data.SqlClient armazena os dados de origem em um buffer de matriz de bytes ou cadeia de caracteres antes da execução para tipos de caractere não (max) e binários, e para os tipos legados Image, Text e NText.
Transmita um valor de parâmetro
Este exemplo envia um arquivo através de um parâmetro varbinary(max) e retorna o número de bytes recebidos. Ele não armazena o valor:
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");
Mantenha o objeto de entrada aberto até a execução do comando concluir. Passe um token de cancelamento para um método de execução assíncrona ou chame Cancel para solicitar o cancelamento da operação de streaming. O cancelamento é feito em regime de melhor esforço. A operação pode ser concluída antes que o cancelamento entre em vigor.
Uma exceção no fluxo de origem ou no leitor causa falha na execução do comando. Não tente novamente a partir do mesmo objeto a menos que consiga estabelecer sua posição e a operação do banco de dados seja segura para repetir.
Transmitir dados de um banco de dados SQL para outro
Este exemplo passa um fluxo de documento do AdventureWorks diretamente para um parâmetro em outro SqlConnection aberto chamado destinationConnection. O comando de exemplo informa o comprimento recebido. Substitua-o pelo comando parametrizado de inserção ou atualização do banco de dados de destino:
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());
}
Os comandos de origem e destino não compartilham uma transação. Se sua aplicação exigir trabalho atômico coordenado entre servidores, projete e teste essa fronteira de transação separadamente.