Russian Qt Forum

Qt => Базы данных => Тема начата: Odyssey от Март 31, 2011, 09:24



Название: Странный эффект при попытке закрыть соединение
Отправлено: Odyssey от Март 31, 2011, 09:24
Здравствуйте!

Пишу функцию, внутри которой требуется открыть соединение с БД, отработать запрос, а затем его закрыть.
Вначале действовал банально:

Код:
someFunction(...) {
    ...
    QSqlDatabase dbSC = QSqlDatabase::addDatabase("QPSQL", CONNECT_NAME);
    dbSC.setHostName("...");
    dbSC.setPort(...);
    dbSC.setDatabaseName("...");
    dbSC.setUserName("...");
    dbSC.setPassword("...");

    if (!dbSC.open()) {
        //Нет связи с БД
    }

    else {
        ...
        QSqlQuery query("...", dbSC);
        ...
    }

    if (dbSC.isOpen()) { dbSC.close();}
    return;
}

Эту функцию вызывал в программе несколько раз. И вот тут мне начали выдавать сообщения, что соединение CONNECT_NAME, оказывается, закрыто не было и его переподключают. Я знал правило, что для корректного закрытия соединения нельзя оставлять открытых запросов (и, добавлю, неудаленных динамически созданных моделей). Но запрос, вроде, создавался в стеке и должен был заблаговременно уничтожаться по выходе из оператора else.

Начал камлать, дополнительно эксперементируя с функцией QSqlDatabase::removeDatabase(CONNECT_NAME) и пытаясь прибить соединение лопатой. Выяснил, что данная функция работает, но только тогда, когда уничтожена и переменная запроса, и переменная dbSC! Пришлось ставить скобки "в чистом поле".

Код:
someFunction(...) {
    ...
   { <----------!!
    QSqlDatabase dbSC = QSqlDatabase::addDatabase("QPSQL", CONNECT_NAME);
    dbSC.setHostName("...");
    ...

    if (!dbSC.open()) {
        //Нет связи с БД
    }

    else {
        ...
        QSqlQuery query("...", dbSC);
        ...
    }

  }  <------------!!!

    QSqlDatabase::removeDatabase(CONNECT_NAME);

    return;
}

Вроде, всё работает, но всё равно хочу уяснить - что это было, за что и правильно ли я это понял? )))


Название: Re: Странный эффект при попытке закрыть соединение
Отправлено: aliks-os от Март 31, 2011, 21:30
Попробуй в своем первоначальном варианте, написать концовку в следующем виде
Код:
    if (!dbSC.open()) {
        //Нет связи с БД
    }

    else {
        ...
        QSqlQuery query("...", dbSC);
        ...
        query.clear();
    }

    if (dbSC.isOpen()) { dbSC.close();}
    return;


Название: Re: Странный эффект при попытке закрыть соединение
Отправлено: asvil от Март 31, 2011, 22:24
Все нормально, читайте статьи, как Qt работает с Sql, и как закрывается соединение. Вкратце, при вызове removeConnection должны быть _уничтожены_ все *Sql* (и даже QSqlDatabase) объекты использующие данное подключение.


Название: Re: Странный эффект при попытке закрыть соединение
Отправлено: Odyssey от Апрель 01, 2011, 15:11
aliks-os

Это я тоже делал - эффекта нет.

Филоненко Михаил

То есть dbSC.close не считается за уничтожение? )) А есть ли какая-нибудь отдельная команда на уничтожение?


Название: Re: Странный эффект при попытке закрыть соединение
Отправлено: asvil от Апрель 01, 2011, 15:59
Да, явный вызов деструктора:) dbSC.~QSqlDatabase(); Правда чревато проблемами.

Принцип работы с Sql в Qt заключается в следующем.
Вы подключение создали (QSqlDatabase::addDatabase() ), вызвали open, а сам объект QSqlDatabase удалили (или он сам удалился).
Потом в любом другом месте программы, Вы захотели опять SQL выполнить, вы объект QSqlDatabase получаете из QSqlDatabase::database(), и как только он Вам не нужен Вы его опять удаляете (или он сам выходит за область видимости и удаляется).
А потом в самом конце программы Вы безо всяческих там, делаете QSqlDatabase::removeDatabase.

Точно так же с QSqlQuery. Как только нужен Вы его создаете, как только не нужен удаляете. Никаких там указателей. Все на стеке.

Вам просто нужно на мгновение забыть все эти рассказы об ООП и c++.

P.S. Исправлено


Название: Re: Странный эффект при попытке закрыть соединение
Отправлено: MoPDoBoPoT от Апрель 01, 2011, 20:41
Можно без лишних скобок.
Код
C++ (Qt)
   QSqlDatabase dbSC = QSqlDatabase::addDatabase("QPSQL", CONNECT_NAME);
   ...
   dbSC = QSqlDatabase();
   QSqlDatabase::removeDatabase(CONNECT_NAME);
 


Название: Re: Странный эффект при попытке закрыть соединение
Отправлено: Odyssey от Апрель 04, 2011, 09:00

Принцип работы с Sql в Qt заключается в следующем.
Вы подключение создали (QSqlDatabase::addDatabase() ), вызвали connect, а сам объект QSqlDatabase удалили (или он сам удалился)...

А где же (и к чему) там делается connect? (Вообще можно даже не объяснять, если трудно, а кинуть мне ссылку на статью).


Название: Re: Странный эффект при попытке закрыть соединение
Отправлено: asvil от Апрель 04, 2011, 09:15
Простите ошибся, не connect, а open.
Полноценные статьи qthelp://com.trolltech.qt.460/qdoc/sql-connecting.html в assistant.


Название: Re: Странный эффект при попытке закрыть соединение
Отправлено: Odyssey от Апрель 04, 2011, 12:22
Спасибо большое! )