2012-10-03 22 views
13

Sto riscontrando un problema durante la scrittura delle quantità grandi di nella colonna FILESTREAM su SQL Server. In particolare, i file di dimensioni ridotte intorno a 1,5-2 GB vengono gestiti correttamente, ma quando le dimensioni raggiungono 6 GB e oltre, ricevo intermittenteIOException "L'handle non è valido" su .CopyTo() verso la fine del trasferimento.Come scrivere file di grandi dimensioni su SQL Server FILESTREAM?

Ho pensato di scrivere i dati in blocchi, ma SQL Server copia il file di supporto per il campo prima di consentire l'aggiunta di dati ad esso, che distrugge completamente le prestazioni per file di grandi dimensioni.

Ecco il codice:

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

Forse guardare http://msdn.microsoft.com/en-us/library/bb933972(v=sql.105) .aspx – Paparazzi

+0

Esiste un esempio generico che scrive _9_ byte nel campo. – chase

+0

Forse un timeout sulla connessione. Hai provato ad aumentare i timeout della connessione, ad esempio. A proposito, mi chiedo, perché stai usando SQL Server per file così grandi? Sta diventando una pratica comune su SQL Server in questi giorni? – ziya

risposta

3

vorrei suggerire di usare BufferedStream Classe intorno vostra classe FileStream.

Assicurarsi inoltre di impostare la proprietà WriteTimeOut nella classe SqlFileStream.

Qui potete trovare un ottimo post che spiega tutto ciò che riguarda SqlFileStream http://www.simple-talk.com/sql/learn-sql-server/an-introduction-to-sql-server-filestream/

+0

Nonostante i documenti, WriteTimeout non è supportato e genererà un'eccezione InvalidOperationException dal flusso sottostante, almeno nella 4.0 – user875318

+0

che è un vero peccato, anche solo per sottolineare che non è necessario utilizzare bufferedstream su un FileStream come dalla versione recente di. funzionalità di buffering di rete è stata aggiunta a FileStream. – dmportella

2

Come suggerito da alcuni dei commenti, il problema è probabilmente un timeout della transazione. È possibile verificare ciò eseguendo SQL Server Profiler e verificando il rollback della transazione.

Se non diversamente specificato, machine.config ha un timeout massimo predefinito di 10 minuti, che non può essere ignorato tramite codice. Per aumentare il timeout massimo, aggiungere quanto segue l'impostazione di configurazione del vostro machine.config

<system.transactions> 
    <machineSettings maxTimeout="00:30:00" /> 
</system.transactions> 
Problemi correlati