Компактный обходной путь Hacky Sql

Итак, я пытаюсь использовать ADO.NET для потоковой передачи файловых данных, хранящихся в столбце изображения в базе данных SQL Compact.

Для этого я написал класс DataReaderStream, который принимает средство чтения данных, открытый для последовательного доступа, и представляет его как поток, перенаправляя вызовы Read (...) в потоке на IDataReader.GetBytes (...).

Один «странный» аспект IDataReader.GetBytes (...) по сравнению с классом Stream заключается в том, что GetBytes требует, чтобы клиент увеличивал смещение и передавал его при каждом вызове. Он делает это, даже если доступ является последовательным, и невозможно читать "назад" в потоке чтения данных.

Реализация SqlCeDataReader IDataReader обеспечивает это, увеличивая внутренний счетчик, который определяет общее количество возвращенных байтов. Если вы передадите число, меньшее или большее, чем это число, метод выдаст исключение InvalidOperationException.

Однако проблема заключается в том, что в реализации SqlCeDataReader есть ошибка, из-за которой внутренний счетчик устанавливает неправильное значение. Это приводит к тому, что последующие вызовы Read в моем потоке выдают исключения, когда их не должно быть.

Я нашел информацию об ошибке на этот поток MSDN.

Мне удалось придумать отвратительный, ужасно хитрый обходной путь, который в основном использует отражение для обновления поля в классе до правильного значения.

Код выглядит так:

    public override int Read(byte[] buffer, int offset, int count)
    {
        m_length  = m_length ?? m_dr.GetBytes(0, 0, null, offset, count);

        if (m_fieldOffSet < m_length)
        {
            var bytesRead = m_dr.GetBytes(0, m_fieldOffSet, buffer, offset, count);
            m_fieldOffSet += bytesRead;

            if (m_dr is SqlCeDataReader)
            {
                //BEGIN HACK
                //This is a horrible HACK.
                    m_field = m_field ?? typeof (SqlCeDataReader).GetField("sequentialUnitsRead", BindingFlags.NonPublic | BindingFlags.Instance);
                    var length = (long)(m_field.GetValue(m_dr));
                    if (length != m_fieldOffSet)
                    {   
                        m_field.SetValue(m_dr, m_fieldOffSet);
                    }
                //END HACK
            }

            return (int) bytesRead;
        }
        else
        {
            return 0;
        }
    }

По понятным причинам я бы предпочел не использовать это.

Однако я также не хочу буферизовать все содержимое большого двоичного объекта в памяти.

Кто-нибудь знает, как я могу получить потоковые данные из базы данных SQL Compact, не прибегая к такому ужасному коду?

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
2
0
563
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я связался с Microsoft (через блог SQL Compact), они подтвердили ошибку и предложили мне использовать OLEDB в качестве временного решения. Итак, я попробую это и посмотрю, сработает ли это для меня.

Ответ принят как подходящий

Собственно, я решил решить проблему, просто не сохраняя капли в базе данных с самого начала.

Это устраняет проблему (я могу передавать данные из файла), а также исправляет некоторые проблемы, с которыми я мог столкнуться с ограничением размера Sql Compact 4 ГБ.

Другие вопросы по теме