Как получить длинное необработанное поле без буферизации всех данных
Всем привет,
Я прошу вашей помощи в попытке решить мою проблему.
Я не знаю, как получить длинное необработанное поле без буферизации всех данных из курсора, отправленного моей хранимой процедурой.
Я хочу обработать каждую запись одну за другой, чтобы избежать любого риска взрыва оперативной памяти.
Есть ли способ загрузить все двоичное содержимое моего поля (dj.doc) в память в моем объекте (dto) без использования InitialLONGFetchSize = -1 ?
Спасибо за Ваши советы.
Я работаю на сервере баз данных Oracle 10g с клиентом Oracle v12 (32 бита) и Visual Studio Pro 2017 (15.4.5) с языком C#
public static void Extract2Files(string scodeUF) { IDbCommand command = GetStoredProcCommand("GetAllOnlyForUF"); command.Parameters.Add(CreateParameter("pin_id_unite_m", scodeUF, 12)); command.Parameters.Add(CreateOutputCursorParameter("t_cursor")); command.InitialLONGFetchSize = -1; command.Connection.Open(); OracleDataReader reader = (OracleDataReader)command.ExecuteReader(); // if (reader.HasRows) // <== this command is buffering all datas from the cursor sent by th stored procédure. I don't want this behavior ! //{ DtoParser parser = DtoParserFactory.GetParser(typeof(T)); parser.PopulateOrdinals(reader); while (reader.Read()) // <== this command is buffering all datas from the cursor sent by th stored procédure. I don't want this behavior ! { T dto = default(T); // null; dto = (T)parser.PopulateDto(reader); ... } reader.Close(); //}
В функции PopulateDto, я вызываю функцию, называемую GetBinaryFromReaderInOnePass.
Приведенный ниже код работает только при выполнении команды.InitialLONGFetchSize = -1
Если команда.InitialLONGFetchSize = 0 значение retval всегда равно 0.
static public byte[] GetBinaryFromReaderInOnePass(IDataReader rdr, int ordinalBinaire) // Size of the BLOB buffer. int totalBinaryBufferSize = (int)rdr.GetBytes(ordinalBinaire, startIndex, null, 0, 0); // The BLOB byte[] buffer to be filled by GetBytes byte[] outByte = new byte[totalBinaryBufferSize]; // Read bytes into outByte[] and retain the number of bytes returned. retval = rdr.GetBytes(ordinalBinaire, startIndex, outByte, 0, totalBinaryBufferSize);
Вот сохраненный процесс, где dj.doc это длинное поле необработанного типа :
PROCEDURE GetAllOnlyForUF(pin_id_unite_m VARCHAR2, cur_docsJoints out t_cursor) IS BEGIN OPEN cur_docsJoints FOR SELECT dj.IDT, dj.name, dj.doc FROM TB_PAT_DOC_JOINT dj, TB_MVT m WHERE dj.id_mvt = m.id_mvt AND m.id_unite_m = pin_id_unite_m; END GetAllOnlyForUF;
Что я уже пробовал:
Когда я использую команду.InitialLONGFetchSize = -1, оперативная память заполняется всеми двоичными файлами моего курсора. Это нецелесообразно с тысячами записей, где каждый двоичный файл весит 2 Мб
Когда я использую команду.InitialLONGFetchSize = 0, я не могу определить размер длинного необработанного поля (DOC) с помощью метода GetBytes
Когда я использую команду.InitialLONGFetchSize = 4096, все мои двоичные файлы имеют размер 4 КБ.
для восстановления всего двоичного файла не было предпринято никаких операций с базой данных туда и обратно.
Я не могу найти выхода ...