Обновить представление списка с изменениями в таблице - PullRequest
2 голосов
/ 08 мая 2009

У меня есть база данных SQLite, которая содержит огромный набор сообщений журнала.

Я хочу отобразить это в виде списка (используя wxWidgets).

Пользователь может изменить порядок списка (нажав заголовок столбца), применить фильтр к набору результатов и перемещаться по нему в виде обычного списка, используя полосу прокрутки. Пользователь также может выбрать одну или несколько записей в списке и удалить их.

У меня есть модель виртуального списка: представление списка запрашивает у модели содержимое определенной строки. Модель выдает запрос на выборку с текущими условиями и порядком фильтра и возвращает соответствующую строку из результата.

Чтобы сделать это быстрее, я сохраняю кэши страниц результатов: когда запрашивается строка, я выбираю целую страницу (~ 100 строк), используя LIMIT и OFFSET, и возвращаю конкретную строку со страницы. Я храню несколько страниц, и в следующий раз при запросе строки я сначала проверяю, доступна ли она на одной из кэшированных страниц. Этот метод оказался быстрым и отзывчивым даже при лотах записей (50k +).

Проблема

Моя проблема в том, как обрабатывать обновления / вставки / удаления. У меня есть один триггер для каждого, поэтому модель уведомляется всякий раз, когда происходит вставка / обновление / удаление. Триггер также сообщает модели идентификатор (первичный ключ) соответствующей записи.

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

Базовый класс модели (wxDataViewVirtualListModel) содержит методы, которые должны вызываться при изменении:

  • RowInserted (строка)
  • RowDeleted (строка)
  • RowChanged (строка)

Если бы я использовал их, проблема выбора была бы решена, однако есть проблемы:

  • Как узнать, находится ли измененная строка в текущем отфильтрованном наборе?
  • Как узнать, какая строка в представлении списка была затронута?

Первая проблема может быть решена путем создания метода, который проверяет, принадлежит ли запись множеству. Он должен вести себя так же, как SQL-условия, но это выполнимо.

Вторая проблема, о которой я просто не знаю, как ее решить.

Я использовал фиктивный (0 или последний ряд) номер строки, чтобы принудительно обновить представление, но проблема в том, что строка была вставлена ​​/ удалена перед выбором, выбор указывает на неправильные строки после, и и так далее.

Как бы вы поступили? Сохранить расширенную структуру данных со всеми записями в памяти?

Этот вопрос связан с другим вопросом: Показать большой набор результатов

1 Ответ

1 голос
/ 08 мая 2009

Я бы разработал это вокруг двух разных операций SELECT, одна получая только первичный ключ и временную метку (INSERT / UPDATE) для всех строк, другая получая все данные для одной страницы строк. На современном компьютере хранение полного списка первичных ключей и временных меток в памяти не должно быть проблемой даже для нескольких 100 000 строк.

Всякий раз, когда меняются критерии фильтра или срабатывает триггер, я снова получаю список первичных ключей и меток времени. Модель поддерживает список первичных ключей и соответствующие временные метки, а сравнение между моделью и новым списком показывает, какие строки необходимо вставить, сделать недействительными или удалить. Кэшированные строки, метка времени которых была изменена, удаляются из кэша, кэшированные строки с той же меткой времени больше не нужно извлекать. Самые старые записи кэша будут удалены, когда он станет слишком большим.

Выбор списка можно определить по значению его первичного ключа, поэтому, если строка не была удалена, всегда можно повторно выбрать его после изменений в модели, даже если он теперь находится в совершенно другой позиции. Я считаю, что это гораздо более интуитивно понятно, чем сохранение одной и той же позиции строки при изменении порядка, при котором выбирается совершенно другая строка.

Edit:

Это работает для одновременных изменений данных от других клиентов баз данных, я реализовал это таким образом для приложений, использующих сервер баз данных Firebird. Если нет возможности изменить данные извне, может не потребоваться всегда получать полный список первичных ключей и временных меток.

...