2011-12-05 9 views
3

CommandBehavior.SequentialAccessを使用してBLOBをストリームとして選択する方法に関する多くの情報が見つかりました。INSERTでBLOBをVARBINARY(MAX)にストリームするには

(BLOBをメモリ内のバイト配列としてキャッシュするのを避けるため)BLOBを挿入するにはストリームを作成したいので、例は見つかりません。私は、と互換性があるUPDATE T-SQLステートメントに.WRITE (expression,@Offset, @Length)という構文を記述したドキュメントを見つけました。だから、私はStreamを受け取り、連続するUPDATE(.WRITE)ステートメントを使ってデータベースにチャンクするクラスを書くことを考えています。これを行うにはこれが正しい方法ですか、それとも良い方法がありますか? UPDATE.WRITEする

リンク:CommandBehavior.SequentialAccessによってを使用してBLOBを選択する

http://msdn.microsoft.com/en-us/library/ms178158(SQL.100).aspx

http://msdn.microsoft.com/en-us/library/ms177523(v=SQL.100).aspx

リンク:

http://msdn.microsoft.com/en-us/library/87z0hy49.aspx

Memory effective way to read BLOB data in C#/SQL 2005

Getting binary data using SqlDataReader

How to make streams from BLOBs available in plain old C# objects when using SqlDataReader?

Streaming VARBINARY data from SQL Server in C#

ここで.WRITE構文を使用してのPOCです:

DDL:

create database BlobTest 
go 
use blobtest 
go 

create table Blob 
(
    Id bigint not null primary key identity(1,1), 
    Data varbinary(max) not null default(0x) 
) 

のC#:

using System.Data; 
using System.Data.SqlClient; 
using System.IO; 
using System.Linq; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main() 
     { 
      string pathToBigFile = "C:\\bigfile.big"; 
      int optimumBufferSizeForSql = 8040; //See https://stackoverflow.com/questions/5629991/how-can-i-generate-an-insert-script-for-a-table-with-a-varbinarymax-field 

      long newBlobId = InitialiseNewBlobInSqlServer(); 

      using (Stream stream = new FileStream( pathToBigFile, 
                FileMode.Open, 
                FileAccess.Read, 
                FileShare.ReadWrite)) 
      { 
       byte[] buffer = new byte[optimumBufferSizeForSql]; 

       while(true) 
       { 
        int numberBytesRead = stream.Read(buffer, 0, optimumBufferSizeForSql); 

        if (numberBytesRead == 0) 
        { 
         //Done 
         break; 
        } 

        WriteBufferToSqlServer(
         numberBytesRead == optimumBufferSizeForSql ? buffer : buffer.Take(numberBytesRead).ToArray(), 
         newBlobId); 
       } 
      } 
     } 

     static long InitialiseNewBlobInSqlServer() 
     { 
      using (SqlConnection conn = new SqlConnection("Data Source=localhost; Initial Catalog=BlobTest; Integrated Security=SSPI;")) 
      using (SqlCommand command = new SqlCommand()) 
      { 
       command.Connection = conn; 
       command.CommandType = CommandType.Text; 
       command.CommandText = "Insert into blob (Data) values (0x); select convert(bigint,Scope_identity());"; 

       conn.Open(); 
       return (long) command.ExecuteScalar(); 
      } 
     } 

     static void WriteBufferToSqlServer(byte[] data, long blobId) 
     { 
      using (SqlConnection conn = new SqlConnection("Data Source=localhost; Initial Catalog=BlobTest; Integrated Security=SSPI;")) 
      using (SqlCommand command = new SqlCommand()) 
      { 
       command.Connection = conn; 
       command.CommandType = CommandType.Text; 
       command.Parameters.AddWithValue("@id", blobId); 
       command.Parameters.AddWithValue("@data", data); 
       command.CommandText = "Update Blob set Data.Write(@data, null, null) where Id = @id;"; 

       conn.Open(); 
       command.ExecuteNonQuery(); 
      } 
     } 
    } 
} 
+0

SqlFileStreamの方がパフォーマンスが向上し、SQL DBの負荷は大幅に軽減されますが、SQL2008以上が必要です。 http://msdn.microsoft.com/en-us/library/system.data.sqltypes.sqlfilestream.aspx – Bengie

+0

ありがとう@Bengie、これはいいですが、私はFILESTREAMではなくデータベースにインラインでデータを格納する必要があります。 –

答えて

1

ブロブを処理するには、SQL ServerのRBSインターフェイスを使用する必要があります。

+0

ありがとう@ハサン。これは非常に興味深いですが、直接私を助けません。私の要件のために、データベースにBLOBを保持したいと思います。 RBSチームブログでは、FileStoreLibrary BlobStoreの例に加えて、FILESTREAMでバックアップされたBlobStoreを作成したことに言及しています。 Add Onとサンプルコードをダウンロードしているので、FileStreamにストリームするかどうか調べることができます(私は疑問に思うので、FILESTREAMに直接アクセスするためにWin32を使用すると期待しています)。 –

+0

RBSコードとFileStream BlobStoreのSQLを見て、データをインラインで(つまりFILESTREAMではなくVARBINARY(MAX)に)格納するオプションがありますが、store_inline = trueに設定されている場合はRBSはストリーミングしませんBLOBを最大25個のブロックに分割し、sprocのパラメータとして分離し、sproc(rbs_fs_sp_store_blob_params)内のデータをvarbinary(max)ブロックにまとめます。それを一度に挿入します。 –

+0

データを行に格納してストリームしたいとします。これらの2つの要件はうまくいっていません。特に挿入の場合。 –

関連する問題