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

前端之家收集整理的这篇文章主要介绍了qt – 何时或如何在QSqlTableModel上使用fetchMore()并使用SQLite数据库使rowCount()工作?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我的类DataTable派生自QAbstractTableModel.它在内部使用QsqlTableModel对象从db表中获取数据.它表示db中每一行的记录(它执行的操作更多,但记录计数始终是db表中的行数).

使用@L_301_0@,我的DataTable :: rowCount()实现只调用QsqlTableModel上的rowCount(),这很好用.

现在使用sqlite,如果db表中有超过256行,Qt的sqlite驱动程序返回的行数为256,因此我的DataTable类也返回256 – 这是错误的. documentation告诉我调用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).

因此,似乎必须在sql模型上的每次写操作之后调用fetchMore().但是,而不是在修改模型的每个方法的末尾放置/ canFetchMore()/ 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()中获取
断言(sql_model->!canFetchMore())

这是因为rowCount()无法报告正确的行计数对我来说是故障状态,因此断言.换句话说,我宁愿让我的应用程序崩溃而不是使用不正确的行数.

只需将它连接到dataChanged()信号(如first answer中所述:我可能会尝试使用dataChanged信号.)是不够的.我已将它连接到dataChanged(const QModelIndex&,const QModelIndex&),rowsInserted(const QModelIndex&,int,int),rowsRemoved(const QModelIndex&,int)和layoutChanged().

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

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

根据我的经验,Qt的sqlite驱动程序以256行的步长将行插入到模型中.在数据提取结束时,QsqlTableModel :: rowCount()将返回正确的值,因此无需调用fetchMore().它只取决于你在何时何地调用rowCount().

例如,如果用户正在对rowsInserted()信号进行一些计算,则他的插槽方法将被多次调用,并且每次最后一行的索引将递增最多值256.

因此,您需要在数据提取结束时使用rowCount()(在某些重写的QsqlTableModel方法中,提取通常不会完成),或者不依赖于中间行计数值并在每次更改时重复计算.

这是一般答案,因为您没有发布任何代码,我们可以看到您正在尝试做什么,但您可以看到我指向的位置.

编辑:

调用QsqlTableModel :: submitAll()之后,重新填充模型,这就是为什么需要再次重复fetchMore()的原因.调用fetchMore()的位置取决于用例.它可以在submitAll()之后调用,或者在某个插槽中,这里没有一般答案.我可能会尝试使用dataChanged信号.但是,获取数据的目标始终应该是主要的,以便在视图中显示它,并且视图在大多数情况下自行完成.

在我的一个应用程序中,我依靠表视图来为我提取数据.在将模型设置为表视图后,我要么调用QTableView :: scrollToBottom()为我提取数据(用户应该在我的情况下看到底部的最新数据,滚动后行数有正确的值)或者在rowsInserted中进行计算当用户滚动表时,()插槽,并再次以256行的步长自动获取数据.

并且非常重要的是要知道,如果应用程序需要在表格中显示某些行数,或者例如一个列数据的汇总值,使用额外的QSqlQuery获取其他信息(如:从xyz中选择count(*))然后从大型表模型中读取数据通常要高效得多.表模型主要用于向表视图提供数据.

猜你在找的Sqlite相关文章