C# 3.5를 사용하여 SQL 2005 이미지 필드를 읽는 가장 메모리 효율적인 방법은 무엇입니까?C#/SQL 2005에서 BLOB 데이터를 읽는 메모리 효율적인 방법
지금은 (byte[])cm.ExecuteScalar("...")
입니다.
모든 필드 내용을 메모리로 읽을 수 없다면 좋을 것입니다.
C# 3.5를 사용하여 SQL 2005 이미지 필드를 읽는 가장 메모리 효율적인 방법은 무엇입니까?C#/SQL 2005에서 BLOB 데이터를 읽는 메모리 효율적인 방법
지금은 (byte[])cm.ExecuteScalar("...")
입니다.
모든 필드 내용을 메모리로 읽을 수 없다면 좋을 것입니다.
자세한 설명은이 article here 또는 blog post을 참조하십시오.
기본적으로 SqlDataReader를 사용하여 만들고 만들 때 을 지정해야합니다. 그런 다음 BLOB를 데이터베이스에서 가장 적합한 크기로 읽거나 쓸 수 있습니다.
는 기본적으로 뭔가 같은 :
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();
마크
트릭은 여기 순차 모드가 ExecuteReader를 사용하고 IDataReader
에서 데이터를 읽는 것입니다. Here's a version for CLOBs - BLOB는 사실상 동일하지만, byte[]
및 GetBytes(...)
입니다.
뭔가 같은 :
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;
}
}
}
다시 말해, 누군가이 대답을보고 위의 내 의견을 놓친 경우 : 반드시 CommandBehavior.SequentialAccess를 설정해야합니다. 그것이 잠시 동안 작동하는 것처럼 보일지 모르지만 일시적인 BLOB 크기의 바이트 배열을 사용하여 프로세스를 깔끔하게 처리 할 것이고 더 큰 BLOB 추출에서 OutOfMemoryException을 얻을 수 있습니다! – Tao
@Tao - 아직 두 가지 답변에서 우리는 그 점을 기억하고 있습니다; p –
예, 방금 누군가가 놓친 앱 코드에서 코드가 발견되어 커다란 혼란을 야기 시켰습니다. 나는 대답을 비판하지 않고 단지 내 상황에있는 누군가에게 유용한 정보를 더하고있다. 이것은 내 최고의 검색 결과 중 하나였으며 앞으로 참조 할 수 있도록이 유용한 정보를 추가 할 수있는 유일한 정보입니다. 내가 그것을 밖으로 내놓는 것이 중요하다고 생각하는 이유는 "SequentialAccess"가 없다면 그것이 작동하는 것처럼 보입니다 ... 그리고 나는 책임있는 개발자가 올바르게 구현되었다고 확신했습니다. – Tao
점에서 몇 가지 중요한 문제가 있습니다; 당신은 데이터 오프셋을 증가시키지 않고 마지막 블록이 완전한 버퍼로드가 아니면 최종 버퍼를 처리하지 않습니다 ... –
데이터 오프셋이 증가하고 있다고 생각합니다 (startIndex + = bufferSize) - 아니? 예 - 마지막 불완전한 버퍼는 여기에 표시되지 않습니다 - 이것은 제가 링크 된 더 긴 기사에서 발췌 한 것입니다. 이것은 메커니즘의 가장 중요한 부분을 설명하기위한 것입니다. ** 완전한 코드가 아닙니다 ** –
OK; 오프셋에서 "내 잘못";-) –