2016-09-07 3 views
-1

정보를 읽기/쓰기 위해 데이터베이스에 접근해야하는 사용자 지정 Stream 클래스를 작성했습니다. XxAsync 데이터베이스 메서드를 사용하려고 했으므로 동기식 읽기/쓰기 메서드에서 connection.OpenAsync()을 사용할 수 없기 때문에 동기식 및 비동기식 메서드를 모두 스트림에 작성하는 것이 좋습니다. 그러나Stream.CopyToAsync는 WriteAynsc 메서드를 호출하지 않습니다.

, 두 버전을 모두 구현 후, 나는 다음)합니다 (간단한 콘솔 응용 프로그램의 무효 홈페이지에 다음과 같은 호출 대상으로 방법이 스트림을 사용하는 경우 :

Task.Run(async() => 
{ 
    using (var ctx = new JobContext()) 
    { 
     // create AssemblyCache record and get assemblyKey... 

     using (var fs = new System.IO.FileStream(@"C:\BTR\Source\Assemblies\BTR.Rbl.Evolution.Documents.dll", 
            System.IO.FileMode.Open, 
            System.IO.FileAccess.Read, 
            System.IO.FileShare.None, 
            8192, 
            true)) 
     using (var bs = ctx.GetBinaryWriteStream<AssemblyCache>(assemblyKey)) 
     { 
      await fs.CopyToAsync(bs); 
     } 
    } 
}).Wait(); 

결코 전화를 보인다 내 XxAsync 메서드. 동기 버전 만 추적합니다. Stream 기본 클래스의 소스를 보면 CopyToAsync가 내 WriteAsync 메서드를 호출해야하므로 내가 무엇을 놓치고 있는지 알 수 없습니다.

UPDATE는

그것은 내 GetBinaryWriteStream 확장 (의도적으로) 압축을 지원하기 위해 내 사용자 지정 스트림 주위에 GZipStream를 래핑 밝혀졌습니다. GZipStreamWriteAsync을 호출하지 않은 원인입니다. 이 질문과 관련하여 새로운 질문을했습니다. here

+0

무엇 너는하려고하는거야 ?? 데이터베이스를 스트림 (stream)으로 취급하는 것은 매우 나쁜 생각입니다. 단순히 데이터베이스가 스트림이 아니기 때문입니다. 당신의 메소드는 라인을 파싱하고, 값을 분리하고, 레코드를 "비동기식"메소드로 데이터베이스에 보내야합니다. 전체 ETL 프로세스를 숨겨서 아무 것도 얻을 수 없지만 코드를 읽고 실행하기가 훨씬 어려워집니다. 예를 들어, 행을 하나씩 보내는 것은 SqlBulkCopy로 행 배치를 보내는 것보다 훨씬 느립니다. –

+0

ETL 작업에 대한 적절한 추상화는 데이터 흐름입니다. 파일에서 행을 읽고, 파싱하고, 변환하고, 마지막으로 배치하고 데이터베이스로 보내는 동시 단계의 파이프 라인입니다. 그건 그렇고, SSIS가하는 일입니다. –

+0

varbinary 열에 (때로는 매우 큰) 파일을 스트리밍합니다. – Terry

답변

2

SqlClient's streaming support을 사용하여 클라이언트의 데이터를 서버의 BLOV (즉, varbinary (MAX)) 열로 스트리밍 할 수 있습니다. INSERT를 수행하는 데 사용하는 것과 거의 동일한 코드를 사용하지만 SQL 명령에 값을 전달하는 대신 스트림 또는 스트림 판독기를 전달합니다. 당신이 많은 파일을 보내려면 예를 들어, 대신

var sql="INSERT INTO [MyTable] (blobField) VALUES (@data)" 
using (SqlConnection conn = new SqlConnection(connectionString)) 
using (SqlCommand cmd = new SqlCommand(sql, conn)) 
{ 
    cmd.Parameters.Add("@data", SqlDbType.Binary, myBuffer.Length).Value = myBuffer; 
    await conn.OpenAsync(); 
    await cmd.ExecuteNonQueryAsync(); 
} 

을 사용하는 당신은 루프에서 매개 변수에 스트림을 할당 할 수

var sql="INSERT INTO [MyTable] (blobField) VALUES (@data)" 
using (SqlConnection conn = new SqlConnection(connectionString)) 
using (SqlCommand cmd = new SqlCommand(sql, conn)) 
{ 
    await conn.OpenAsync(); 
    using (FileStream file = File.Open("binarydata.bin", FileMode.Open)) 
    { 
     cmd.Parameters.Add("@data", SqlDbType.Binary, -1).Value = file; 
     await cmd.ExecuteNonQueryAsync(); 
    } 
} 

을 써서 :

var blobParam=cmd.Parameters.Add("@data", SqlDbType.Binary, -1); 
    foreach(var somePath in aListOfPaths) 
    { 
     using (FileStream file = File.Open(somePath, FileMode.Open)) 
     { 
      blobparam.Value = file; 
      await cmd.ExecuteNonQueryAsync(); 
     } 
    } 
+0

이 길로 가려고합니다. 데이터 압축에 대한 귀하의 생각이 궁금합니다. http://stackoverflow.com/questions/40346948/compressing-data-with-a-gzipstream-stream-wrapper-when-using-sqlclient-streaming에 다른 질문을했습니다. – Terry

+0

무엇을하려하십니까? SQL Server는 이미 테이블 데이터 및 FILESTREAM 파일 압축 [압축 된 볼륨에 저장 가능]을 지원합니다 (https://msdn.microsoft.com/en-us/library/gg471497.aspx#FILESTREAM+Storage) –

관련 문제