Мой класс DataTable получен из QAbstractTableModel. Он использует объект QSqlTableModel внутри для извлечения данных из таблицы db. Он представляет запись для каждой строки в db (она делает больше, но количество записей всегда - количество строк в таблице db).Когда или как использовать fetchMore() в QSqlTableModel с базой данных SQLite для функции rowCount()?
С помощью MySql моя реализация DataTable :: rowCount() просто вызывает rowCount() в QSqlTableModel, который работает хорошо.
Теперь с SQLite, драйвер SQLite Qt возвращает число строк 256, если в таблице db содержится более 256 строк, поэтому мой класс DataTable также возвращает 256 - это неверно. documentation говорит мне позвонить по телефону while (sql_model->canFetchMore()) sql_model->fetchMore();
. Вызов fetchMore() сразу после создания внутренней QSqlTableModel фактически вызывает следующий вызов rowCount() для возврата правильного значения. Но как только что-то изменится в базе данных (мой класс вызовет insertRow() или setData() в QSqlTableModel), следующий вызов QSqlTableModel :: rowCount() снова вернется 256.
База данных изменяется только по моему классу, который, в свою очередь, использует этот конкретный объект QSqlTableModel (или представление, которое использует мою модель DataTable как модель, может что-то обновить). Таким образом, нет другого процесса, который мог бы вставлять строки в базу данных.
Итак, когда класс DataTable должен вызвать fetchMore() для rowCount(), чтобы всегда возвращать фактический счетчик строк?
Я думаю, что мой класс должен подключить некоторые из сигналов, испускаемых QSqlTableModel, к слоту, который будет вызывать fetchMore(), хотя Я не уверен, что это правильный/надежный способ сделать это?
Update:
Вот код, чтобы продемонстрировать основную проблему.
QSqlTableModel *model = new QSqlTableModel(0, database); //QSqlDatabase
model->setTable("tablename");
qDebug() << "0 row count" << model->rowCount(); //0 row count 0
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
model->select();
qDebug() << "1 row count" << model->rowCount(); //1 row count 256
while (model->canFetchMore()) model->fetchMore();
qDebug() << "2 row count" << model->rowCount(); //2 row count 1520
//... other methods ...
model->setData(model->index(0, 0), "TEST");
model->submitAll();
qDebug() << "3 row count" << model->rowCount(); //3 row count 256
while (model->canFetchMore()) model->fetchMore();
qDebug() << "4 row count" << model->rowCount(); //4 row count 1520
После загрузки модели SQL, ROWCOUNT() возвращает 256 (1), так что fetchMore() должен быть вызван. rowCount() затем возвращает фактическое количество строк.
Позже данные изменяются, после чего rowCount() снова возвращает 256 (3).
Похоже, что fetchMore() необходимо вызвать после каждой операции записи в модели sql. Но вместо того, чтобы помещать этот цикл while/canFetchMore()/fetchMore() в конец каждого метода, который модифицирует модель, мне интересно, достаточно ли подключить beforeInsert (QSqlRecord &), beforeUpdate (int, QSqlRecord &) и beforeDelete (int) в слот, который затем вызывает fetchAll()? Будет ли это надежным и уместным?
Коррекция: Не раньше * сигналов (слишком рано), но, вероятно, layoutChanged(), dataChanged(), rowsInserted() и rowsRemoved().
Update 2:
Примечание относительно SQL: Я знаю, что я мог бы послать отдельный запрос SELECT COUNT
SQL в базе данных в теории, но это не дает ответа на вопрос. Пока я могу избежать SQL, я не буду писать SQL. На мой взгляд, отправка такого SQL-запроса не соответствует цели объектно-ориентированного класса QAbstractTableModel.Плюс rowCount() является const (не должен отправлять запросы) и должен быть быстрым. Во всяком случае, это не будет исправлять rowCount().
я в конечном итоге подключение слота, который вызывает fetchMore() к соответствующим сигналам (смотрите выше) И утверждать, что все было выбрано во ROWCOUNT():
assert(!sql_model->canFetchMore())
Это потому, что ROWCOUNT() неспособность сообщить правильное количество строк подсчета как состояние отказа для меня, следовательно, утверждение. Другими словами, я бы предпочел, чтобы мое приложение потерпело крах, чем использование неправильного количества строк.
Недостаточно просто подключить его к сигналу dataChanged(), как предложено в first answer: I would probably try to use dataChanged signal.
). Я подключил его к dataChanged(const QModelIndex&, const QModelIndex&)
, rowsInserted(const QModelIndex&, int, int)
, rowsRemoved(const QModelIndex&, int, int)
и layoutChanged()
.
Кажется, что работа еще не завершена.
Если кто-то может конкретно подтвердить это (или объяснить, почему он не всегда будет работать), я был бы признателен за ответ.
Спасибо за ваш ответ. Я добавил код на вопрос. Я хотел бы знать, следует ли мне называть fetchMore() всякий раз, когда срабатывают сигналы (см. Вопрос). Кроме того, я не уверен, что вы подразумеваете под «вам нужно использовать rowCount() в конце извлечения данных», как вызов rowCount() исправить rowCount() (возвращение 256)? И если я могу на самом деле «не полагаться на подсчет промежуточных строк», то мне, вероятно, придется прочитать всю таблицу в памяти при загрузке (работа в памяти) и подсчитать строки в памяти (звучит расточительно) вместо вызова rowCount() ... – basic6
Привет!Я обновил свой ответ. Может быть, это может помочь вам немного. – user645859
Ответ на ваш комментарий: Я не сказал, что _calling rowCount() исправит rowCount() _, но использовать rowCount() только тогда, когда все данные будут извлечены, а не раньше. – user645859