使用MySql,我的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().
似乎工作,断言还没有失败.
如果有人能够明确证实这一点(或解释为什么它不会一直有效),我会很感激答案.
例如,如果用户正在对rowsInserted()信号进行一些计算,则他的插槽方法将被多次调用,并且每次最后一行的索引将递增最多值256.
因此,您需要在数据提取结束时使用rowCount()(在某些重写的QsqlTableModel方法中,提取通常不会完成),或者不依赖于中间行计数值并在每次更改时重复计算.
这是一般答案,因为您没有发布任何代码,我们可以看到您正在尝试做什么,但您可以看到我指向的位置.
编辑:
在调用QsqlTableModel :: submitAll()之后,重新填充模型,这就是为什么需要再次重复fetchMore()的原因.调用fetchMore()的位置取决于用例.它可以在submitAll()之后调用,或者在某个插槽中,这里没有一般答案.我可能会尝试使用dataChanged信号.但是,获取数据的目标始终应该是主要的,以便在视图中显示它,并且视图在大多数情况下自行完成.
在我的一个应用程序中,我依靠表视图来为我提取数据.在将模型设置为表视图后,我要么调用QTableView :: scrollToBottom()为我提取数据(用户应该在我的情况下看到底部的最新数据,滚动后行数有正确的值)或者在rowsInserted中进行计算当用户滚动表时,()插槽,并再次以256行的步长自动获取数据.
并且非常重要的是要知道,如果应用程序需要在表格中显示某些行数,或者例如一个列数据的汇总值,使用额外的QSqlQuery来获取其他信息(如:从xyz中选择count(*))然后从大型表模型中读取数据通常要高效得多.表模型主要用于向表视图提供数据.