crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

3 страниц V   1 2 3 >  
Ответить в данную темуНачать новую тему
> Некорректное закрытие QSqlDatabase, при использовании QSqlTableModel
Гость_silver_*
сообщение 4.8.2008, 18:27
Сообщение #1





Гости








    


Здравствуйте!

Использую в простеньком приложении QSqlTableModel для отображения и редактирования таблицы.
При закрытии программы выдаёт предупреждение

QSqlDatabasePrivate::removeDatabase: connection 'qt_sql_default_connection' is still in use, all queries will cease to work.


Пробовал в деструкторе окна, где используется модель, делать вещи вроде
model->clear();
delete model;


не помогает :(

Оно, вроде бы, и нестрашно, но как-то неправильно. Кто-нибудь сталкивался с таким?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 4.8.2008, 18:39
Сообщение #2


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9656
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(Гость_silver_* @ 4.8.2008, 22:27) *
Кто-нибудь сталкивался с таким?

ты БД закрываешь?
принципиально соеденение удалять нужды нет
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
silver
  опции профиля:
сообщение 4.8.2008, 21:45
Сообщение #3


Новичок


Группа: Новичок
Сообщений: 8
Регистрация: 4.8.2008
Из: Харьков
Пользователь №: 250

Спасибо сказали: 1 раз(а)




Репутация:   0  


Всё, разобрался!
Дело было в том, что я использовал не только QSqlTableModel, но и фильтрующую QSortFilterProxyModel. Так вот последняя при удалении не освобождает модель-источник! Что в общем-то и логично. Всё решается либо явным удалением модели-источника, либо указанием для неё в качестве родителя прокси-модели:

    modelFilter = new QSortFilterProxyModel(this);
    modelSource = new QSqlTableModel(modelFilter);
    modelSource->select();
    modelFilter->setSourceModel(modelSource);
    view = createView(modelFilter);


Причём именно в таком порядке, т.к. удаление модели-источника раньше прокси-модели недопустимо!

Пишу так много, потому что полдня потратил на такую глупость, может кому пригодится...

Сообщение отредактировал silver - 4.8.2008, 22:26
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 4.8.2008, 22:18
Сообщение #4


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9656
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


вообще это известное предупреждение и видно его только в консоли.

Удалять соединение нет нужды - вот от правная точка!
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
silver
  опции профиля:
сообщение 4.8.2008, 22:30
Сообщение #5


Новичок


Группа: Новичок
Сообщений: 8
Регистрация: 4.8.2008
Из: Харьков
Пользователь №: 250

Спасибо сказали: 1 раз(а)




Репутация:   0  


Цитата(Litkevich Yuriy @ 4.8.2008, 22:18) *
вообще это известное предупреждение и видно его только в консоли.


Я думаю, теоретически, может произойти потеря данных, поэтому лучше правильно закрывать все активные запросы ДО завершения соединения.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ViGOur
  опции профиля:
сообщение 5.8.2008, 11:52
Сообщение #6


Мастер
******

Группа: Модератор
Сообщений: 3293
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 4

Спасибо сказали: 231 раз(а)




Репутация:   40  


Цитата(silver @ 4.8.2008, 23:30) *
поэтому лучше правильно закрывать все активные запросы ДО завершения соединения.
Это правильная практика, ИМХО, что сам создал, то и удалил (открыл -> закрыл).
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
acen83
  опции профиля:
сообщение 6.8.2008, 8:28
Сообщение #7


Студент
*

Группа: Участник
Сообщений: 23
Регистрация: 11.2.2008
Пользователь №: 91

Спасибо сказали: 0 раз(а)




Репутация:   0  


QSqlDataBase* bd=QSqlDataBase::addConnection("QMYSQL");
// настройка базы, логина и т.п.
bd->open();
// запросы
bd->close();


затем в другом месте программы повторяя этот код появляется предупреждение

QSqlDatabasePrivate::removeDatabase: connection 'qt_sql_default_connection' is still in use, all queries will cease to work.


Что делать?

Сообщение отредактировал acen83 - 6.8.2008, 8:30
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ViGOur
  опции профиля:
сообщение 6.8.2008, 9:07
Сообщение #8


Мастер
******

Группа: Модератор
Сообщений: 3293
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 4

Спасибо сказали: 231 раз(а)




Репутация:   40  


Читаем описание QSqlDataBase::addConnection:
Цитата
Adds a database to the list of database connections using the driver type and the connection name connectionName. If there already exists a database connection called connectionName, that connection is removed.
По идее QSqlDataBase* bd=QSqlDataBase::addConnection("QMYSQL"); нужно вызывать один раз и bd желательно сделать глобальным или синглтоном.

Если же ты хочешь создать две копии QSqlDataBase, то используй второй параметр addConnection для их именования...
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 6.8.2008, 12:58
Сообщение #9


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9656
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(acen83 @ 6.8.2008, 12:28) *
Что делать?

если тебе надо использовать уже созданое тобой соединение то используй так:
QSqlDatabase app_db = QSqlDatabase::database();

Перевод из SVN-хранилища:
Цитата
Подробное описание
Класс QSqlDatabase предоставляет подключение к базе данных.
Класс QSqlDatabase предоставляет абстрактный интерфейс для доступа к базе данных. Он использует конкретный QSqlDriver базы данных для доступа и манипуляции данными.
В следующем коде показано как установить соединение:
     QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL");
     db.setHostName("acidalia");
     db.setDatabaseName("customdb");
     db.setUserName("mojito");
     db.setPassword("J0a1m8");
     bool ok = db.open();

После создания объекта QSqlDatabase, устанавливаем параметры соединения с помощью setDatabaseName(), setUserName(), setPassword(), setHostName(), setPort(), и setConnectOptions(). Только после установки параметров вызывается open() для открытия соединения.
Соединение определеное выше — безымянное соединение. Это соединение по умолчанию и доступ к нему может быть получен позже используя database():
     QSqlDatabase db = QSqlDatabase::database();

Чтобы сделать програмирование более удобным, QSqlDatabase реализован как класс-значение (англ. "value class"). Любые изменения сделаные в соединении с базой данных через один объект QSqlDatabase будут влиять на другие объекты QSqlDatabase представляющие это же соединение. Вызовите cloneDatabase(), если вы хотите создать независимое соединение с базой данных на основе существующего.
Если вы нуждаетесь во множестве соединений с базами данных одновременно, определите произвольное имя в addDatabase() и database(). Вызовите removeDatabase(), чтобы удалить соединение. QSqlDatabase выведет предупреждение, если вы попытаетесь удалить соединение, указанное в других объектах QSqlDatabase. Используйте contains(), чтобы видеть если заданное имя соединения есть в списке соединений.
Как только соединение установлено вы можете посмотреть, какие таблицы база данных предоставляет с помощью tables(), найти первичный индекс для таблицы с помощью primaryIndex(), получить мета-информацию о полях таблицы (например, их имена) с помощью record() и выполнить запрос с помощью exec().
Если транзакции поддерживаются, вы можете использовать transaction(),чтобы начать транзакцию, и затем commit() или rollback(), чтобы завершить ее. Вы можете узнать поддерживается ли транзакция используя QSqlDriver::hasFeature(). При использовании транзакции вы должны начать транзакцию, прежде чем создадите свой запрос.
Если произошла ошибка, она может быть получена с помощью lastError().
Имена SQL драйверов доступны из drivers(), вы можете проверить доступность драйвера с помощью isDriverAvailable(). Если вы создали свой собственный драйвер, вы можете зарегистрировать его с помощью registerSqlDriver().
Смотрите также QSqlDriver, QSqlQuery, Модуль QtSql и Потоки и Модуль QtSql.


Цитата
QSqlDatabase QSqlDatabase::addDatabase ( const QString & type, const QString & connectionName = QLatin1String( defaultConnection ) ) [static]
Добавляет базу данных в список соединений баз данных используя драйвер type и имя соединения connectionName. Если уже существует соединение с базой данных называющееся connectionName, этосоединение удаляется.
Соединения с базой данных в дальнейшем именуется connectionName. Вновь добавленое соединение будет возвращено.
Если параметр connectionName не определен, внови добавленное соединение становится для приложения соединением поумолчанию, и последующие вызовы database() без параметра вернут ссылку на него. Если connectionName задан, используйте database(connectionName), чтобы вернуть указатель на соединение.
Предупреждение: Если вы добавите базу данных с тем же именем как и у существующей базы данных, старая база данных будет заменена новой. Это происходит автоматически, если вы вызываете эту функцию больше, чем один раз без указания connectionName.
Чтобы использовать соединение, вам нужно настроить его, например, вызвав некоторые или все из фунций setDatabaseName(), setUserName(), setPassword(), setHostName(), setPort(), и setConnectOptions(), а затем вам нужно открыть соединение с помощью open().
Замечание: Эта функция потокобезопасная.
Смотрите также database(), removeDatabase(), и Драйвера баз данных SQL.


acen83, silver, почитайте вот эту тему Базы данных
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
silver
  опции профиля:
сообщение 6.8.2008, 14:43
Сообщение #10


Новичок


Группа: Новичок
Сообщений: 8
Регистрация: 4.8.2008
Из: Харьков
Пользователь №: 250

Спасибо сказали: 1 раз(а)




Репутация:   0  


Цитата(acen83 @ 6.8.2008, 8:28) *
Что делать?


Скорее всего, у тебя остаются висеть незакрытые запросы. Причём не обязательно именно QSqlQuery, но и в виде QSqlQueryModel, QSqlTableModel и так далее по иерархии. Убедись, что к моменту закрытия соединения, все твои модели и запросы либо выходять из области видимости (если создавались на стеке):
 {
     QSqlDatabase db = QSqlDatabase::database("sales");
     QSqlQuery query("SELECT NAME, DOB FROM EMPLOYEES", db);
}
// Both "db" and "query" are destroyed because they are out of scope
QSqlDatabase::removeDatabase("sales"); // correct


либо удаляются оператором delete или родителем (если создал их как QSqlQuery *query = new QSqlQuery). В моём случае проблема была именно в этом.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

3 страниц V   1 2 3 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 4.12.2020, 4:58