2009-09-28 17 views

Respuesta

4

Consulte este excelente article here o este blog post para obtener una explicación larga de cómo hacerlo.

Básicamente, debe usar un SqlDataReader y especificar SequentialAccess al crearlo, entonces puede leer (o escribir) el BLOB de la base de datos en fragmentos del tamaño que sea mejor para usted.

Básicamente algo como:

SqlDataReader myReader = getEmp.ExecuteReader(CommandBehavior.SequentialAccess); 

while (myReader.Read()) 
{ 
    int startIndex = 0; 

    // Read the bytes into outbyte[] and retain the number of bytes returned. 
    retval = myReader.GetBytes(1, startIndex, outbyte, 0, bufferSize); 

    // Continue reading and writing while there are bytes beyond the size of the buffer. 
    while (retval == bufferSize) 
    { 
     // write the buffer to the output, e.g. a file 
     .... 

     // Reposition the start index to the end of the last buffer and fill the buffer. 
     startIndex += bufferSize; 
     retval = myReader.GetBytes(1, startIndex, outbyte, 0, bufferSize); 
    } 

    // write the last buffer to the output, e.g. a file 
    .... 
} 

// Close the reader and the connection. 
myReader.Close(); 

Marc

+0

Hay algunos problemas importantes en eso; no está incrementando el offset de datos, y no está procesando el búfer final si el último bloque no es una carga de búfer completa ... –

+1

Creo que el desplazamiento de datos se está incrementando (startIndex + = bufferSize) - ¿no? Sí - el último buffer incompleto no se muestra aquí - esto es un extracto del artículo más largo al que me he vinculado, para ilustrar los aspectos más importantes del mecanismo: ** no ** es una pieza de código de trabajo completa –

+0

OK; "my bad" en el offset ;-p –

2

El truco aquí es usar ExecuteReader en modo secuencial, y leer los datos de la IDataReader. Here's a version for CLOBs - BLOB son prácticamente idénticos, pero con un byte[] y GetBytes(...).

Algo así como:

using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) 
{ 
    byte[] buffer = new byte[8040]; // or some multiple (sql server page size) 
    while (reader.Read()) // each row 
    { 
     long dataOffset = 0, read; 
     while ((read = reader.GetBytes(
      colIndex, dataOffset, buffer, 0, buffer.Length)) > 0) 
     { 
      // TODO: process "read"-many bytes from "buffer" 
      dataOffset += read; 
     } 
    } 
} 
+0

Nuevamente, en caso de que alguien mire esta respuesta y se haya perdido mi comentario anterior: DEBE establecer CommandBehavior.SequentialAccess. Si no lo hace, podría parecer que está funcionando por un tiempo, pero estará ensuciando su proceso con arreglos temporales de tamaño de blob, ¡y eventualmente obtendrá OutOfMemoryException en extracciones de blob más grandes! – Tao

+0

@Tao - aún en ambas respuestas recordamos agregar eso; p –

+0

Sí, acabo de encontrar un código en nuestra aplicación donde alguien había echado de menos eso, y causó un gran lío. No estoy criticando las respuestas, solo agrego más información útil para alguien en mi situación. Este fue uno de mis principales resultados de búsqueda, y el único en el que puedo agregar esta útil información útil para referencia futura. La razón por la que creo que es importante publicarlo es que sin el "Acceso Secuencial" parece que está funcionando ... Y creo que el desarrollador responsable estaba satisfecho de que se haya implementado correctamente. – Tao

Cuestiones relacionadas