何时或如何在QSqlTableModel上使用fetchMore()并使用SQLite数据库为rowCount()工作?

bas*_*ic6 5 sqlite qt qsqltablemodel qsqldatabase

我的类DataTable派生自QAbstractTableModel.它在内部使用QSqlTableModel对象从db表中获取数据.它表示db中每一行的记录(它执行的操作更多,但记录计数始终是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 
Run Code Online (Sandbox Code Playgroud)

加载sql模型后,rowCount()返回256(1),因此必须调用fetchMore().然后rowCount()返回实际的行数.
之后,数据被更改,之后rowCount()再次返回256(3).

因此,似乎必须在sql模型上的每次写操作之后调用fetchMore().但是在/ modFetchMore()/ fetchMore()循环中,而不是在每个修改模型的方法结束时,我想知道是否足以连接beforeInsert(QSqlRecord&),beforeUpdate(int,QSqlRecord&)和beforeDelete(int)发信号到一个槽,然后调用fetchAll()?这是否可靠和合适?

更正:不在*信号之前(太早),但可能是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().

似乎工作,断言还没有失败.

如果有人能够明确证实这一点(或解释为什么它不会一直有效),我会很感激答案.

bas*_*ic6 1

当前的答案没有完全回答问题(提到 dataChanged() 信号,但没有提到其他信号),所以我正在编写自己的答案。

已经有一段时间了,我相信我已经涵盖了所有情况:我最终将一个调用 fetchMore() 的插槽连接到相关信号,并断言所有内容都已在我的 DataTable::rowCount() 方法中获取:assert(!sql_model- >canFetchMore())

(当然 rowCount() 是一个 const 方法,所以如果还没有获取任何内容,我就无法获取,但这无论如何都不是 getter 的工作;断言很好,因为 canFetchMore() 也是 const。)

信号:dataChanged(const QModelIndex&,const QModelIndex&),rowsInserted(const QModelIndex&,int,int),rowsRemoved(const QModelIndex&,int,int)和layoutChanged()

我使用断言来确保我的模型收到正确的行数,否则应用程序将崩溃(如果未连接所有提到的信号,例如layoutChanged(),则会发生这种情况)。这对我来说很重要,因为不正确的行计数可能会导致数据丢失。

到目前为止,断言尚未失败,所以我假设这可以解决问题。