2012-10-03 27 views
13

大量のの量のSQL ServerのFILESTREAM列への書き込みに問題があります。具体的には、1.5〜2GB程度の小さなファイルは問題なく処理されますが、サイズが6GB以上になると、が断続的になりますIOException転送の最後には.CopyTo()にハンドルが無効です。大きなファイルをSQL Server FILESTREAMに書き込む方法は?

データをチャンクに書き込むことを考えましたが、SQL Serverは大きなファイルのパフォーマンスを完全に破壊するデータを追加する前に、フィールドのバッキングファイルをコピーします。

は、ここでは、コードです:

public long AddFragment (string location , string description = null) 
{ 
    const string sql = 
     @"insert into [Fragment] ([Description],[Data]) " + 
      "values (@description,0x); " + 
     "select [Id], [Data].PathName(), " + 
      "GET_FILESTREAM_TRANSACTION_CONTEXT() " + 
     "from " + 
      "[Fragment] " + 
     "where " + 
      "[Id] = SCOPE_IDENTITY();"; 

    long id; 

    using (var scope = new TransactionScope(
     TransactionScopeOption.Required, 
      new TransactionOptions { 
       Timeout = TimeSpan.FromDays(1) 
      })) 
    { 
     using (var connection = new SqlConnection(m_ConnectionString)) 
     { 
      connection.Open(); 

      byte[] serverTx; 
      string serverLocation; 

      using (var command = new SqlCommand (sql, connection)) 
      { 
       command.Parameters.Add("@description", 
        SqlDbType.NVarChar).Value = description; 

       using (var reader = command.ExecuteReader()) 
       { 
        reader.Read(); 
        id = reader.GetSqlInt64(0).Value; 
        serverLocation = reader.GetSqlString (1).Value; 
        serverTx = reader.GetSqlBinary (2).Value; 
       } 
      } 

      using (var source = new FileStream(location, FileMode.Open, 
       FileAccess.Read, FileShare.Read, 4096, 
       FileOptions.SequentialScan)) 
      using (var target = new SqlFileStream(serverLocation, 
       serverTx, FileAccess.Write)) 
      { 
       source.CopyTo (target); 
      } 
     } 

     scope.Complete(); 
    } 

    return id; 
} 
+0

たぶんhttp://msdn.microsoft.com/en-us/library/bb933972(v=sql.105を見て、あなたのmachine.configの構成設定に以下を追加します).aspx – Paparazzi

+0

フィールドに_9_バイトを書き込む一般的な例があります。 – chase

+0

接続にタイムアウトが発生している可能性があります。たとえば、接続タイムアウトを増やしてみましたか?ところで、ちょうど不思議なことに、なぜあなたは大きなファイルにSQL Serverを使用していますか?これらは最近、SQL Server上で一般的なプラクティスになっていますか? – ziya

答えて

3

私はあなたがあなたのFileStreamクラスの周りBufferedStreamクラスを使用することをお勧め。

またSqlFileStreamクラスのWriteTimeOutプロパティを設定していることを確認してください。ここで

あなたはコメントのいくつかによって示唆されるようにSqlFileStream http://www.simple-talk.com/sql/learn-sql-server/an-introduction-to-sql-server-filestream/

+0

ドキュメントにもかかわらず、WriteTimeoutはサポートされておらず、基盤となるストリームからInvalidOperationExceptionをスローします。最低でも – user875318

+0

であることは恥ずかしいです。また、最近のバージョンのFileStreamでbufferedstreamを使用する必要もありません。ネットバッファリング機能がFileStreamに追加されました。 – dmportella

2

についてのすべてを説明本当に良い記事を見つけ、問題はおそらく、トランザクションのタイムアウトです。これを確認するには、SQL Server Profilerを実行し、ロールバックするトランザクションを監視します。

特に指定しないかぎり、machine.configのデフォルトmaxTimeoutは10分です。これはコードで上書きすることはできません。最大タイムアウトを増やすには、

<system.transactions> 
    <machineSettings maxTimeout="00:30:00" /> 
</system.transactions> 
関連する問題