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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Странный эффект при попытке закрыть соединение  (Прочитано 4188 раз)
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;
}

Вроде, всё работает, но всё равно хочу уяснить - что это было, за что и правильно ли я это понял? )))
« Последнее редактирование: Март 31, 2011, 12:21 от Odyssey » Записан
aliks-os
Гость
« Ответ #1 : Март 31, 2011, 21:30 »

Попробуй в своем первоначальном варианте, написать концовку в следующем виде
Код:
    if (!dbSC.open()) {
        //Нет связи с БД
    }

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

    if (dbSC.isOpen()) { dbSC.close();}
    return;
Записан
asvil
Гость
« Ответ #2 : Март 31, 2011, 22:24 »

Все нормально, читайте статьи, как Qt работает с Sql, и как закрывается соединение. Вкратце, при вызове removeConnection должны быть _уничтожены_ все *Sql* (и даже QSqlDatabase) объекты использующие данное подключение.
Записан
Odyssey
Гость
« Ответ #3 : Апрель 01, 2011, 15:11 »

aliks-os

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

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

То есть dbSC.close не считается за уничтожение? )) А есть ли какая-нибудь отдельная команда на уничтожение?
Записан
asvil
Гость
« Ответ #4 : Апрель 01, 2011, 15:59 »

Да, явный вызов деструктора:) dbSC.~QSqlDatabase(); Правда чревато проблемами.

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

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

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

P.S. Исправлено
« Последнее редактирование: Апрель 04, 2011, 09:14 от Филоненко Михаил » Записан
MoPDoBoPoT
Гость
« Ответ #5 : Апрель 01, 2011, 20:41 »

Можно без лишних скобок.
Код
C++ (Qt)
   QSqlDatabase dbSC = QSqlDatabase::addDatabase("QPSQL", CONNECT_NAME);
   ...
   dbSC = QSqlDatabase();
   QSqlDatabase::removeDatabase(CONNECT_NAME);
 
Записан
Odyssey
Гость
« Ответ #6 : Апрель 04, 2011, 09:00 »


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

А где же (и к чему) там делается connect? (Вообще можно даже не объяснять, если трудно, а кинуть мне ссылку на статью).
Записан
asvil
Гость
« Ответ #7 : Апрель 04, 2011, 09:15 »

Простите ошибся, не connect, а open.
Полноценные статьи qthelp://com.trolltech.qt.460/qdoc/sql-connecting.html в assistant.
Записан
Odyssey
Гость
« Ответ #8 : Апрель 04, 2011, 12:22 »

Спасибо большое! )
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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