전체 값을 애플리케이션 메모리에 먼저 로드하지 않고도 큰 값을 처리하려면 Microsoft.Data.SqlClient 스트리밍 메서드를 사용하세요. 스트리밍은 바이너리 파일, 대형 텍스트, XML, JSON, 서버 간 전송에 유용합니다.
스트리밍이 그 값을 seek 가능하게 하거나 reader에서의 동시 작업을 안전하게 만들지는 않습니다. 연결, 명령, 리더, 소스 스트림, 목적지 객체는 전송이 완료될 때까지 살아 있어야 합니다.
이 글의 예에서는 AdventureWorks 샘플 데이터베이스를 대상으로 하는 열려 있는 SqlConnectionconnection을 가정합니다.
C# 예제는 using Microsoft.Data.SqlClient;를 요구합니다.
SqlDbType 또는 CommandBehavior를 사용하는 예시도 using System.Data;가 필요합니다.
SQL 데이터베이스에서 데이터를 스트리밍하기
CommandBehavior.SequentialAccess를 사용하여 명령을 실행하고 열을 순서대로 읽습니다. 순차적 접근에서는 열을 지나면 같은 행의 이전 열을 읽지 마세요.
다음 SqlDataReader 방법을 사용하세요:
| 메서드 | 결과 | 일반적인 SQL 데이터 |
|---|---|---|
| GetStream | Stream | 이진, varbinary, 이미지 및 사용자 정의 타입(UDT) 데이터 |
| GetTextReader | TextReader | 문자 및 JSON 데이터 |
| GetXmlReader | XmlReader | xml |
nullable column에 대한 스트림을 요청하기 전에 IsDBNull을 호출하세요. 호환되지 않는 SQL 타입과 함께 사용하면 예외가 발생하는 스트리밍 게터입니다. 다른 열을 읽거나 다음 행으로 이동하거나 다음 결과로 이동하기 전에 현재 스트림을 소비하거나 폐기하세요.
GetStream은 암호화된 열에서 지원되지 않습니다.
GetTextReader 암호화된 열에 순차적으로 접근하는 것을 지원하지 않습니다.
CommandTimeout가 Microsoft.Data.SqlClient가 실행 및 읽기 중 네트워크 패킷을 기다리는 동안 적용됩니다. 애플리케이션이 이미 받은 데이터를 처리하는 데 소요되는 시간은 계산되지 않습니다. 취소 및 타임아웃에 대해서는 비동기식 프로그래밍을 참조하세요.
바이너리 데이터 스트리밍
AdventureWorks는 파일 내용을 nullable varbinary(max)Production.Document.Document 열에 저장합니다. 이 예시는 경계가 있는 버퍼를 사용해 한 값을 파일에 복사합니다:
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);
}
텍스트에는 GetTextReader를 사용하고 TextWriter로 복사하세요. XML의 경우, 전체 값을 문자열로 변환하지 않고 GetXmlReader를 사용하고 XML 노드를 처리하세요.
SQL 데이터베이스로 데이터를 스트리밍하기
Value을 스트리밍 객체로 설정하고 호환 가능한 SQL 타입을 선택하세요:
| 값 형식 | 호환 가능한 매개변수 유형 |
|---|---|
| Stream |
Binary, VarBinary, 그리고 레거시 Image 타입 |
| TextReader |
Char, NChar, VarChar, NVarChar, 레거시 Text 과 NText 타입, Xml, 그리고 Json |
| XmlReader |
Char, NChar, VarChar, NVarChar, 레거시 Text과 NText 타입, Xml, 그리고 Json |
명시적으로 설정합니다 Size .
Size 이체되는 금액을 제한합니다. 전체 소스를 보내려는 경우 -1 매개변수에 (max)를 사용하세요.
유계 메모리 전송의 경우, NVarChar와 함께 VarBinary, VarChar 또는 Size = -1를 사용하거나, Json 또는 Xml를 사용하세요. Microsoft.Data.SqlClient는 비-Image 문자 및 이진 형식과 레거시 Text, NText, (max) 형식의 경우 실행하기 전에 소스를 바이트 배열 또는 문자열로 버퍼링합니다.
매개변수 값을 스트리밍하기
이 예시는 varbinary(max) 매개변수를 통해 파일을 전송하고 수신된 바이트 수를 반환합니다. 값을 저장하지 않습니다:
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");
명령 실행이 완료될 때까지 입력 객체를 열어두세요. 취소 토큰을 비동기 실행 메서드에 전달하거나 스트리밍 작업 취소를 요청하려면 Cancel를 호출합니다. 취소는 가능한 범위에서 처리됩니다. 작업이 취소가 적용되기 전에 완료될 수도 있습니다.
소스 스트림이나 리더 폴트에서 발생한 예외는 명령 실행에 오류를 발생시킵니다. 위치를 확인할 수 있고 데이터베이스 작업을 안전하게 반복할 수 있는 경우가 아니면 같은 객체에서 재시도하지 마세요.
한 SQL 데이터베이스에서 다른 SQL 데이터베이스로 데이터를 스트리밍하기
이 예시는 AdventureWorks 문서 스트림을 이름이 SqlConnection인 다른 열린 destinationConnection의 매개변수에 직접 전달합니다. 샘플 명령어는 수신된 길이를 보고합니다. 목적지 데이터베이스의 매개변수화된 삽입 또는 업데이트 명령어로 대체하세요:
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());
}
소스와 목적지 명령어는 트랜잭션을 공유하지 않습니다. 애플리케이션이 서버 간 조정된 원자 작업이 필요하다면, 해당 트랜잭션 경계를 별도로 설계하고 테스트하세요.