我的类 DataTable 是从 QAbstractTableModel 派生的。它在内部使用 QSqlTableModel 对象从 db 表中获取数据。它代表数据库中每一行的记录(它做得更多,但记录计数始终是数据库表中的行数)。
使用 MySql,我的 DataTable::rowCount() 实现只需调用 QSqlTableModel 上的 rowCount(),效果很好。
现在使用 SQLite,如果 db 表中有超过 256 行,Qt 的 SQLite 驱动程序会返回 256 的行数,所以我的 DataTable 类也返回 256 - 这是错误的。文档告诉我打电话给while (sql_model->canFetchMore()) sql_model->fetchMore();
. 在创建内部 QSqlTableModel 之后立即调用 fetchMore() 实际上会导致以下 rowCount() 调用返回正确的值。但是一旦数据库中的某些内容发生了变化(我的类将在 QSqlTableModel 上调用 insertRow() 或 setData()),下一个 QSqlTableModel::rowCount() 调用将再次返回 256。
数据库仅由我的类修改,而我的类又使用该特定的 QSqlTableModel 对象(或使用我的 DataTable 作为模型的视图可以更新某些内容)。所以没有其他进程可以将行插入数据库。
那么我的 DataTable 类何时应该为 rowCount() 调用 fetchMore() 以始终返回实际的行数?
我在想我的班级应该将 QSqlTableModel 发出的一些信号连接到一个可以调用 fetchMore() 的插槽,尽管我不确定这是否是正确/可靠的方法?
更新:
这是一些代码来演示基本问题。
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()?这会是可靠和适当的吗?
更正:不是 before* 信号(太早),但可能是 layoutChanged()、dataChanged()、rowsInserted() 和 rowsRemoved()。
更新 2:
关于 SQL 的注意事项:我知道SELECT COUNT
理论上我可以向数据库发送单独的 SQL 查询,但这并不能回答问题。只要能避免SQL,我就不会写SQL。在我看来,发送这样的 SQL 查询违背了面向对象的 QAbstractTableModel 类的目的。加上 rowCount() 是 const (不应该发送查询)并且应该很快。无论如何,这不会修复 rowCount()。
我最终将一个调用 fetchMore() 的插槽连接到相关信号(见上文)并断言所有内容都已在 rowCount() 中获取:
assert(!sql_model->canFetchMore())
这是因为 rowCount() 无法向我报告正确的行数计数为失败状态,因此断言。换句话说,我宁愿我的应用程序崩溃也不愿使用不正确的行数。
仅将其连接到 dataChanged() 信号(如第一个答案中所建议的:)I would probably try to use dataChanged signal.
是不够的。我已将其连接到dataChanged(const QModelIndex&, const QModelIndex&)
、rowsInserted(const QModelIndex&, int, int)
和。rowsRemoved(const QModelIndex&, int, int)
layoutChanged()
似乎有效,断言还没有失败。
如果有人可以特别确认这一点(或解释为什么它并不总是有效),我将不胜感激。