如何使用 QDatastream 通过 QTcpSocket 发送 QSqlQueryModel?

How to send QSqlQueryModel over QTcpSocket with QDatastream?

我想使用 QDatastream 和 QTcpSocket 将 QSqlQueryModel 发送到另一个客户端。我想删除一些行并向 QSqlQueryModel 添加一些额外的行(不更改数据库)并将其发送给客户端,就像这样的伪代码:-

QTcpSocket socket;
socket.setSocketDescriptor(handle);
socket.waitForReadyRead(WAIT_TIME);

QByteArray req = socket->readAll();
QDataStream reqstream(&req,QIODevice::ReadOnly);

QSqlQueryModel MyModel;
....
// fetch data with MyModel
// add/remove some rows from that model without adding/removing them from actual database
....

QByteArray res;
QDataStream resstream(&res,QIODevice::WriteOnly);
resstrem << MyModel;
socket.write(res);

如何在不创建模型的新深层副本的情况下实现此。在客户端,它应该只接收一个带有数据的模型,以便我可以在 QML 中显示它。

如果不创建 "deep copy."

,您将无法在 Qt 中做您想做的事,或与此相关的任何其他事情

如果您使用的是 real 数据库,而不是 SQLite 或其他一些不使用数据库引擎的低端存储方法,则无需执行转移。阅读 temporary tables for your chosen database. You can SELECT INTO 临时 table。这样效率更高,因为具有活动引擎的数据库只会创建一个指针游标,但将其视为真正的 table。如果生成的游标对于 RAM 而言太大,它将把它写入某个临时暂存区。

之后,只需让您的客户端告诉服务器应用程序删除要从临时 table 中删除的行,然后插入要添加的行。只需确保您的服务器从那时起在临时 table 上运行。

注意:如果您正在处理一个非常糟糕的电子表格示例,该示例将数据结果从 GUI 线程内绑定到电子表格,则您无法修复该问题。我在网上找到的每个官方示例都非常糟糕。永远不要在主事件循环中做数据库I/O。

您可能还想获得一份 this book。它不会包含这个问题的答案,但它确实包含许多工作数据库示例。

QAbstractItemModel 的任何后代的目的是将一些数据采用到可以呈现它们的视图(小部件)中。

所以基本上你是在尝试做一些超出这个 class 设计的事情。这就像试图用铲子敲钉子一样。这是可能的,但很危险,不推荐。

只需使用 QSqlQuery(使用锤子)遍历行读取列并以某种序列化格式存储它们来读取降级数据。您可以为此使用 QDataStream

    QDataStream out{&socket};

    QSqlQuery query{"SELECT country FROM artist"};
    while (query.next()) {
        out << query.value(0).toString();
    }

可以将其设为异步。