Russian Qt Forum
Ноябрь 23, 2024, 20:50 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2]   Вниз
  Печать  
Автор Тема: QSqlTableModel - добавить строку не получается.  (Прочитано 15535 раз)
Alex_C
Гость
« Ответ #15 : Июль 24, 2012, 21:42 »

Во первых - большое спасибо за ответы!
Во вторых - есть куча вопросов по PostgreSQL - но мучить вас я их не буду)))
Давайте наверное опишу саму задачу, чтоб суть проблемы стала ясна:
есть проект на Дельфи (мой проект). Проект очень большой, но большой не в плане работы с БД. Сейчас переделываю его на Qt , но 15 лет программирования на Дельфи сказываются - пытаюсь сделать как там))). Собственно все очень критичные части уже на Qt перенес. Осталась - работа с БД, которая в моем проекте достаточно простая. Хоть есть несколько критичных моментов. Но думал, что проблем не будет... Однако перечитал ВСЕ книги по Qt - все равно вопросы есть))) Это я к тому, что документацию я читаю.
Теперь конктетика.
1. Есть критичная ситуация - время вставки записи в таблицу. При том что в таблице порядка 200 тыс записей (это максимум). Они отображаются в табличном виде.  Вставленные новые записи нужно отображать в таблице. Естественно 200 тыс записей в память никто не считывает - в Дельфи в компоненте ADOQuery есть св-во - данные брать с сервера (постраничное отображение) или целиком скачивать. Тут я такое не нашел.
2. Продолжение предыдущего: в Qt считываются первые 450 записей. Почему первые? А если мне надо последние?
3. И все же мой код на редактирование:
Код
C++ (Qt)
bool LogModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
   QSqlTableModel::setData(index, value, role);
 
   if (index.column() < 1)
       return false;
 
   return updateDataForColumn(getFieldNameByIndex(index.column()), index, value);
}
 
bool LogModel::updateDataForColumn(QString columnName, const QModelIndex &index,
                                  const QVariant &value)
{
   QModelIndex primaryKeyIndex = QSqlQueryModel::index(index.row(), 0);
   int id = QSqlQueryModel::data(primaryKeyIndex).toInt();
 
   QSqlQuery query;
   if (index.column() > 1)
   {
       query.prepare("UPDATE " + globalVariable->logName +
                     " SET " + columnName +
                     " = ? WHERE KeyField = ?");
       query.addBindValue(value.toString());
       query.addBindValue(id);
   }
   bool b = query.exec();
   emit dataChanged(index, index);
   return b;
}
 
 

Работает  очень эффективно и быстро. Редактирование.
В книге Бланшета и Саммерфильда в главе 13 (в книге 2007 года) предлагается нечто подобное.
Вопрос собственно только в одном - как также быстро и эффективно вставлять строки)))
Записан
PavelVX
Гость
« Ответ #16 : Июль 25, 2012, 05:38 »

Тоже присоединяюсь к теме, но маленько с другим вопросом: а как определить, что запись новая?
Ситуация: setEditStrategy(QSqlTableModel::OnManualSubmit); пользователь понавводил/поредактировал данные. Как мне отличить новая это строка или редактирование уже введенной?
Причем isDirty() несколько кривовато работает.
При смене строки в тейблвью смотрю состояние isDirty по предыдущему индексу. После редактирования, при сходе с редактируемой строки, isDirty == false!!!! Однако, если я потом вернусь на эту запись и опять с неё сойду, то isDirty == true Грустный.
Я переопределил в своей модели setData(). По идее, при редактировании isDirty() после setData должен сбрасываться? Или мне что-то надо прописать в этом методе?
« Последнее редактирование: Июль 25, 2012, 06:12 от PavelVX » Записан
Alex_C
Гость
« Ответ #17 : Июль 25, 2012, 08:08 »

Добавление к предыдущему вопросу: а есть ли опять де как в дельфийском TTable определить State: dsInsert, dsEdit - тоже пока это не нашел.
Записан
PavelVX
Гость
« Ответ #18 : Июль 25, 2012, 08:30 »

Добавление к предыдущему вопросу: а есть ли опять де как в дельфийском TTable определить State: dsInsert, dsEdit - тоже пока это не нашел.
Что есть dsInsert, dsEdit? Метки состояния рекорда?
Записан
Alex_C
Гость
« Ответ #19 : Июль 25, 2012, 11:20 »

Да.

Теперь по теме... Прочитал информацию по данному вопросу в инете - не утешительная информация. Qt не умеет читать из БД постранично. Вопрос: может кто озадачивался данной проблемой? Как допустим в табличном виде просмотреть 100 тыс записей, как это сделано в том же MS Access?

В принципе проблему вставки записи/редактирования решил - отдельно вставляю в БД, отдельно в таблицу. Если делать submitAll() - происходит перечитывание всей таблицы, что неверно.
Записан
fte
Гость
« Ответ #20 : Июль 25, 2012, 11:59 »

2 Alex_C

ИМНО: у Вас в голове каша при использовании QSqlTableModel , по факту Вы пытаетесь из него сделать Редактируемую QSqlQueryModel..., в примерах Qt есть простенькая реализация такого класса, тока ее надо расширить и углубить 

Код
C++ (Qt)
bool LogModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
   QSqlTableModel::setData(index, value, role);
 
   if (index.column() < 1)
       return false;
 
   return updateDataForColumn(getFieldNameByIndex(index.column()), index, value);
}

    В Вашем случае: обновляет данные  в кэше, и sumitAll() - непосредственно в базе
    QSqlTableModel::setData(index, value, role);
    ........
    Еще раз обновляем те же данные сразу в базе.....
    return updateDataForColumn(getFieldNameByIndex(index.column()), index, value);

Цитировать
Вопрос собственно только в одном - как также быстро и эффективно вставлять строки)))

Вставка как раз происходит быстро! А вот чтение обновленных данных - медленно....
можно например так - setQuery("select * testtable order by ...... limit кол_во_строк offset строка_номер"
естественно "кол_во_строк" и "строка_номер" модель должна сама определять....
Записан
fte
Гость
« Ответ #21 : Июль 25, 2012, 12:07 »

Наследуйте свою модель от QSqlQueryModel, setData у Вас уже есть,
только вот эту строку выкинуть:    QSqlTableModel::setData(index, value, role);
Вам осталось только InsertRows реализовать, ну и с постраничным выводом разобраться (см. пост выше)
Записан
fte
Гость
« Ответ #22 : Июль 25, 2012, 12:20 »

Цитировать
Как допустим в табличном виде просмотреть 100 тыс записей

Я бы ослеп на второй тысяче...... Непонимающий Неужели все данные нужны сразу, и их можно проанализировать только последовательно листая экранами по ххх строк, 100К записей Непонимающий
Записан
PavelVX
Гость
« Ответ #23 : Июль 26, 2012, 05:01 »

А как определить, до сохранения в базу сабмитом, какие строки редактировались, а какие новые?
Как самому сбросить isDirty?
Записан
fte
Гость
« Ответ #24 : Июль 26, 2012, 11:13 »

2 PavelVX
Цитировать
Как самому сбросить isDirty?
submit(),revert()

Цитировать
А как определить, до сохранения в базу сабмитом, какие строки редактировались, а какие новые?
например использовать сигналы.....
beforeInsert(),beforeUpdate(),beforeDelete()
Записан
Alex_C
Гость
« Ответ #25 : Июль 26, 2012, 11:34 »

Каши как раз в голове нет - просто пытался проблему решить что называется "малой кровью".
И в общем то решил, но решение самому не очень нравится.
Правильное решение вот:

можно например так - setQuery("select * testtable order by ...... limit кол_во_строк offset строка_номер"
естественно "кол_во_строк" и "строка_номер" модель должна сама определять....

однако допустим на том же Access'е я не нашел такого варианта SELECT. Есть только
SELECT TOP 100 ...
но это считывает верхние 100 строк. Хотя учитывая что в Дельфи ADO умеет так делать - решение есть.
Причем если понять как считывать группами из центра таблици, то реализовать подгруздку в таблицу динамически при скроллинге - не проблема.
Записан
Страниц: 1 [2]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.269 секунд. Запросов: 21.