2009-09-28 9 views

Odpowiedz

4

Zobacz ten znakomity article here lub ten blog post, aby uzyskać długie wyjaśnienie, jak to zrobić.

Zasadniczo, musisz użyć SqlDataReader i określić SequentialAccess do niego podczas tworzenia - wtedy możesz odczytać (lub zapisać) BLOB z bazy danych w kawałkach o jakikolwiek rozmiar jest najlepszy dla ciebie.

Zasadniczo coś takiego:

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

Istnieje kilka ważnych problemów w tym; nie zwiększasz przesunięcia danych i nie przetwarzasz bufora końcowego, jeśli ostatni blok nie jest kompletnym ładowaniem bufora ... –

+1

Myślę, że przesunięcie danych jest inkrementowane (startIndex + = bufferSize) - Nie? Tak - ostatni niekompletny bufor nie jest tutaj pokazany - jest to fragment dłuższego artykułu, do którego się przyłączyłem, aby zilustrować najważniejsze fragmenty mechanizmu - to ** nie ** kompletny działający fragment kodu –

+0

OK; "moje złe" w offsecie ;-p –

2

Sztuką jest, aby używać ExecuteReader w trybie sekwencyjnym, a odczyt danych z IDataReader. Here's a version for CLOBs - BLOBy są praktycznie identyczne, ale z byte[] i GetBytes(...).

Coś jak:

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

Jeszcze raz, na wypadek, gdyby ktoś spojrzał na tę odpowiedź i nie zauważył mojego komentarza powyżej: MUSISZ ustawić CommandBehavior.SequentialAccess. Jeśli tego nie zrobisz, może wyglądać, jakby działał przez jakiś czas, ale będziesz zaśmiecał swój proces tymczasowymi tablicami rozmiarów bajtów o rozmiarze blob i ostatecznie uzyska OutOfMemoryException na większych ekstrakcjach kropelkami! – Tao

+0

@Tao - jeszcze w obu odpowiedziach, które zapamiętaliśmy, aby dodać to; p –

+0

Tak, właśnie znalazłem kod w naszej aplikacji, w której ktoś to przegapił - i spowodował wielki bałagan. Nie krytykuję odpowiedzi, tylko dodam trochę informacji przydatnych komuś w mojej sytuacji. Był to jeden z moich najlepszych wyników wyszukiwania i jedyny, w którym mogę dodać tę miejmy nadzieję, przydatną informację, by móc z niej skorzystać w przyszłości. Powodem, dla którego uważam, że ważne jest, aby to ująć, jest to, że bez "SequentialAccess" wygląda to tak, jakby działało ... I myślę, że odpowiedzialny programista był przekonany, że został poprawnie zaimplementowany. – Tao

Powiązane problemy