Как отправить QSqlQueryModel через QTcpSocket с помощью QDatastream?

Я хочу отправить QSqlQueryModel другому клиенту с QDatastream и QTcpSocket. Я хочу удалить несколько строк и добавить несколько дополнительных строк в 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.


person    schedule 06.02.2020    source источник
comment
Что вы подразумеваете под без создания новой глубокой копии?   -  person eyllanesc    schedule 06.02.2020
comment
@eyllanesc Я имею в виду не использовать цикл for для копирования всех записей в новый QList. примерно так: - media.geeksforgeeks.org/wp-content/uploads /   -  person 尤金寶 漢子    schedule 06.02.2020
comment
@尤金寶 漢子 вы не можете отправить объект Qt через TCP. Вы можете отправить только некоторые данные. В QSqlQueryModel данные (item) находятся в индексах. Каждый индекс имеет строку и столбец. Вы не можете получить каждый индекс без цикла. Вам понадобится карта сборки или что-то еще для отправки копии вашей модели. Вы можете наследоваться от QSqlQueryModel и перегрузить метод data() для построения карты для отправки, но я думаю, что все, что вы можете сделать с этим. Самый простой способ сделать это — написать QSqlQuery.   -  person someoneinthebox    schedule 10.02.2020


Ответы (2)


Целью любого потомка QAbstractItemModel является перенос некоторых данных в представления (виджеты ), который может их представить.

Итак, в основном вы пытаетесь сделать что-то, что выходит за рамки дизайна этого класса. Это как пытаться забить гвоздь лопатой. Это возможно, но опасно и не рекомендуется.

Просто прочитайте данные debase, используя QSqlQuery (используйте молоток), переберите строки, прочитайте столбцы и сохраните их в каком-либо формате сериализации. Вы можете использовать QDataStream для этого:

    QDataStream out{&socket};

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

Можно сделать это асинхронным.

person Marek R    schedule 11.02.2020

Вы не можете делать то, что хотите в Qt или что-то еще в этом отношении, не создавая «глубокую копию».

Если вы используете настоящую базу данных, а не SQLite или какой-либо другой низкоуровневый метод хранения, который не использует механизм базы данных, вы можете делать все, что хотите, без переноса. Ознакомьтесь с временными таблицами для выбранной вами базы данных. Вы можете SELECT INTO временную таблицу. Это намного эффективнее, потому что база данных с активным движком просто создаст курсор указателей, но обработает его как настоящую таблицу. Если результирующий курсор слишком велик для оперативной памяти, он запишет его во временную рабочую область.

После этого ваш клиент просто скажет серверному приложению УДАЛИТЬ строки, которые вы хотите удалить из временной таблицы, и ВСТАВИТЬ строки, которые вы хотите добавить. Просто нужно быть уверенным, что с этого момента ваш сервер работает с временной таблицей.

ПРИМЕЧАНИЕ. Если вы работаете с действительно плохим примером электронной таблицы, который привязывает результат данных к электронной таблице из потока графического интерфейса, вы не можете это исправить. Каждый официальный пример, который я нашел в сети, действительно плох. Никогда не выполняйте ввод-вывод базы данных в основном цикле событий.

Вы также можете получить копию этой книги. Он не будет содержать ответа на этот вопрос, но содержит много рабочих примеров баз данных.

person user3450148    schedule 10.02.2020