Russian Qt Forum
Декабрь 18, 2017, 02:15 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Как грамотно закрыть подключение к БД?  (Прочитано 220 раз)
Павелъ
Чайник
*
Offline Offline

Сообщений: 84



Просмотр профиля
« : Декабрь 07, 2017, 13:23 »

Доброго времени суток.

Понадобилось написать функцию, которая проверяет доступность БД.

Есть три СУБД: на Оракле, на ПосгреСКЛ и на МССКЛ.

Функция, возвращающая конечный результат:

Код:
bool CommonFunctions::isConnectedToDataBase(DataBaseInfo dbInfo)
{
    switch (dbInfo.dbType) {
    case dbOracle:
        return isConnectToOracleDataBase(dbInfo);
    case dbMSSQL:
        return isConnectedToMS_SQL_dataBase(dbInfo);
    case dbPosgreSQL:
        return isConnectedToPosgreSQL_dataBase(dbInfo);
    }
    return false;
}


Для Оракле:

Код:
bool CommonFunctions::isConnectToOracleDataBase(DataBaseInfo dbInfo)
{
    QSqlDatabase db = QSqlDatabase::addDatabase("QOCI","Oracle_connection");
    db.setDatabaseName(dbInfo.dataBaseName);
    db.setHostName(dbInfo.ipAddress);
    db.setPort(dbInfo.port);
    db.setUserName(dbInfo.userName);
    db.setPassword(dbInfo.password);

    if(!db.open())
    {
        db.removeDatabase("Oracle_connection");
        return false;
    }

    QSqlQuery query(db);

    query.exec("select * from v$version");

    bool retBool = false;

    if(!query.lastError().type())
    {
        retBool = query.first();
    }

    if(db.isOpen())
    {
        db.close();
    }

    db.removeDatabase("Oracle_connection");

    return retBool;
}

Для МССКЛ:

Код:
bool CommonFunctions::isConnectedToMS_SQL_dataBase(DataBaseInfo dbInfo)
{
    QSqlDatabase db = QSqlDatabase::addDatabase("QODBC3","MS_SQL_connection");

    db.setDatabaseName(getODBCconnectionSettings(dbInfo));

    if(!db.open())
    {
        db.removeDatabase("MS_SQL_connection");
        return false;
    }

    QSqlQuery query(db);

    query.exec("select @@version");

    bool retBool = false;

    if(!query.lastError().type())
    {
        retBool = query.first();
    }

    if(db.isOpen())
    {
        db.close();
    }

    db.removeDatabase("MS_SQL_connection");

    return retBool;
}

Для Посгре:

Код:
bool CommonFunctions::isConnectedToPosgreSQL_dataBase(DataBaseInfo dbInfo)
{
    QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL","PosgreSQL_connection");
    db.setDatabaseName(dbInfo.dataBaseName);
    db.setHostName(dbInfo.ipAddress);
    db.setPort(dbInfo.port);
    db.setUserName(dbInfo.userName);
    db.setPassword(dbInfo.password);

    if(!db.open())
    {
        db.removeDatabase("PosgreSQL_connection");
        return false;
    }

    QSqlQuery query(db);

    query.exec("select version()");

    bool retBool = false;

    if(!query.lastError().type())
    {
        retBool = query.first();
    }

    if(db.isOpen())
    {
        db.close();
    }

    db.removeDatabase("PosgreSQL_connection");

    return retBool;
}

Ну, и вспомогательная функция для соединения с QODBC:

Код:
QString CommonFunctions::getODBCconnectionSettings(DataBaseInfo dbInfo)
{
    return "DRIVER={SQL Server};Server=" + dbInfo.ipAddress + "," + QString::number(dbInfo.port) +";Database=" + dbInfo.dataBaseName + ";Uid=" + dbInfo.userName + ";Pwd=" + dbInfo.password + ";WSID=.";
}



Сначала я создавал подключение к БД таким образом:

Код:
QSqlDatabase db = QSqlDatabase::addDatabase("QOCI");

Но после вызова следующей функции появлялись варнинги о том, что старое соединение удалено, хотя перед возвращением результата я делаю db.close().

Тогда я прочитал, что надо в таком случае указать имя соединения, и я сделал подключение следующим образом:

Код:
QSqlDatabase db = QSqlDatabase::addDatabase("QOCI","Oracle_connection");

добавив имя соединения.

С тремя разными соединениями это прокатывает, но как только я вызываю ещё раз проверку соединения, например для Оракла, то опять появляется сообщение, что старое соединение удалено.

Тогда я решил, что после db.close() сделаю следующее:

Код:
db.removeDatabase("Oracle_connection");

И тут начались варнинги с вылетами приложения:

Код:
QSqlDatabasePrivate::removeDatabase: connection 'MS_SQL_connection' is still in use, all queries will cease to work.


Вопрос в следующем. Есть данные для подключения к БД.
Мне нужно получить ТОЛЬКО информацию о том, есть ли подключение и посылается ли тестовый sql-запрос.
То есть, в функции создаётся соединение, а перед тем, как возвратить результат оно должно полностью закрыться и удалиться из программы.

То есть: есть данные для БД, нужно возвратить её работоспособность и не хранить никаких соединений.

Что я делаю не так, и как это грамотно сделать?

Спасибо.
Записан
Павелъ
Чайник
*
Offline Offline

Сообщений: 84



Просмотр профиля
« Ответ #1 : Декабрь 07, 2017, 14:23 »

Пришла идея проверять наличие соединения с помощью contains а qsqldatabase. При наличии делать соединение к существующей, иначе - создавать.
Записан
Павелъ
Чайник
*
Offline Offline

Сообщений: 84



Просмотр профиля
« Ответ #2 : Декабрь 07, 2017, 17:50 »

Да, так работает.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  

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