crossplatform.ru

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


  Ответ в Некорректное закрытие QSqlDatabase
Введите ваше имя
Подтвердите код

Введите в поле код из 6 символов, отображенных в виде изображения. Если вы не можете прочитать код с изображения, нажмите на изображение для генерации нового кода.
 

Опции сообщения
 Включить смайлы?
Иконки сообщения
(Опционально)
                                
                                
  [ Без иконки ]
 


Последние 10 сообщений [ в обратном порядке ]
fortero Дата 29.4.2011, 16:28
 
Цитата(silver @ 6.8.2008, 14:43) *
Цитата(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). В моём случае проблема была именно в этом.


А Вы можите написать пример как правельно это сделать с передачей в конструктор?
Буду очень признателен!
silver Дата 8.8.2008, 22:33
 
Цитата(acen83 @ 7.8.2008, 18:45) *
Так чтоли?


Ну, как один из вариантов:
    QSqlDatabase db = QSqlDatabase::database("my_very_rarely_used_db");
    if (!db.isValid()) {
            // выполнится только в первый раз, когда соединения ещё нет
        db = QSqlDatabase::addDatabase("QMYSQL", "my_very_rarely_used_db");
        // Заполняем параметры соединения
    }
    db.open();
    // работаем
    db.close();
    // всё, никаких removeDatabase() делать не надо


Хотя я бы всё-таки создал именованное соединение в конструкторе, и не открывал его. Эта операция практически не займёт ни времени, ни ресурсов. Зато когда БД понадобится, можно сразу открывать её и работать, без всяких дополнительных проверок.
acen83 Дата 7.8.2008, 18:45
 
Цитата(silver @ 7.8.2008, 17:01) *
Есть функции QSqlDatabase::isOpen() и QSqlDatabase::isValid(), которые именно это и делают.


Так чтоли?

QSqlDatabase db=QSqlDatabase::database();
if (!db.isValid())
{
db.addConnection("QMYSQL");
// добавление логинов, пассов и т.п.
}
return db;
Litkevich Yuriy Дата 7.8.2008, 16:23
 
Цитата(silver @ 7.8.2008, 20:01) *
Что ещё за сообщение о закрытии старой БД?

да он дважды одно и тоже соединение создает:
Цитата(acen83 @ 6.8.2008, 12:28) *
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.
silver Дата 7.8.2008, 16:01
 
Цитата(acen83 @ 6.8.2008, 18:41) *
Remove database у меня есть, но он закрывает только ругательства о незакрытых запросах, а сообщения о закрытии старой БД все равно остаются :unsure:

Может я чего-то пропустил? Что ещё за сообщение о закрытии старой БД? В первом посте ты указал только одно сообщение: о том, что на момент закрытия соединения остались запросы, которые это соединение используют.

Цитата(acen83 @ 6.8.2008, 18:41) *
Плохо что нет какой-нибудь функции наподобие clear() и соответственно isNull(), для того чтобы определять была инициализирована база или нет. Так получить базу через QSqlDatabase::database() конечно можно, но как проверить была она уже настроена или нет :huh:


Есть функции QSqlDatabase::isOpen() и QSqlDatabase::isValid(), которые именно это и делают.
Litkevich Yuriy Дата 7.8.2008, 8:33
 
Цитата(Litkevich Yuriy @ 7.8.2008, 4:09) *
у меня в классе главного окна создается экземпляр "одиночки"

Да, надо было полнее прокоментировать. Это у меня для авторизации пользователей программы, но там же и соединение с БД хранящих настройки пользователей.

А соединение с основной БД так:
Цитата(Litkevich Yuriy @ 7.8.2008, 4:09) *
далее после конструктора, т.е. после того как окно программы отобразится создается соединение основной БД.
Tonal Дата 7.8.2008, 7:47
  2 Litkevich Yuriy
Нет нужды делать соединение с БД одиночкой, т.к. оно само только удобный интерфейс к реальному соединению, которое уже одиночка.
Вроде с тобой же обсуждали в "переводах" значение value type в данном контексте. :)
Litkevich Yuriy Дата 7.8.2008, 0:09
  у меня в классе главного окна создается экземпляр "одиночки", а внем соединение с БД настроек приложения (это я так решил вместо всяких ини-конфигов сделать). далее после конструктора, т.е. после того как окно программы отобразится создается соединение основной БД.
исходник

MainWindow::MainWindow()
{
    mdiArea = new QMdiArea;
    setCentralWidget(mdiArea);
    connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(updateMenus()));
    
    windowMapper = new QSignalMapper(this);
    connect(windowMapper, SIGNAL(mapped(QWidget *)), this, SLOT(setActiveSubWindow(QWidget *)));

    createActions();    // Создаем действия
    createMenus();        // Создаем меню
    createToolBars();    // Создаем панель инструментов
    createStatusBar();    // Создаем панель статуса
    readWindowSettings();// Читаем настройки окна
    // Создаем экземпляр класса сесии
    auth = Session::InitInstance();    

    
    connect(this, SIGNAL(SigShow()), SLOT(SlotOnShow()));
    
    
}

MainWindow::~MainWindow()
{
    auth->FreeInstance();
}

bool MainWindow::event(QEvent *p_event)
{
    if( p_event->type() == QEvent::ShowToParent)
        emit SigShow();

    return QWidget::event(p_event);
}

/*=====================================================================
                Постинициализация
  ===================================================================*/
void MainWindow::SlotOnShow()
{
  QString    errmsg;
  QString    title = tr("Ошибка программы");

qDebug() << "SlotOnShow: " << QDateTime::currentDateTime() << "\n\r";
  
    // Вход от имени анонимного пользователя
    auth->LoginAnonymous();
    
    // Обновляем меню
    updateMenus();
    
    // Проверяем все ли хорошо с настройками
    if (!auth->isGood(errmsg))
    {
        QMessageBox::critical(this, title, tr("Ошибка настроек, обратитесь к специалисту. Сообщение: \n\r") + errmsg);
        return;
    }
    
    // Здесь проверяется и устанавливается соединение с БД.
  bool ok;
  QSqlDatabase app_db = QSqlDatabase::database("appdb");    // создано в Session::InitInstance();
  QSqlQuery query(app_db);
  QString    querystr;
  QString    qerr;
  
  QString    db_driver;
  QString    db_name;
  QString    db_user_name;
  QString    db_user_paswd;
  
  
    querystr="SELECT F_VALUE FROM APPSETTINGS \
    WHERE ((F_TYPE='db_driver') OR (F_TYPE='db_name') OR \
    (F_TYPE='db_user_name') OR (F_TYPE='db_user_paswd')) \
    ORDER BY F_TYPE ASC";
    ok = query.exec(querystr);
qDebug() << "select DB settings - " << ok << "\n\r";
    
    if (!ok)
    {
        qerr = query.lastError().text();
        QMessageBox::critical(0, title,
                                 tr("Невозможно прочитать настройки БД.\n\r Причина: ")+qerr,
                                QMessageBox::Ok);
    }
    
    query.first();
    if (!query.isValid())
    {
        qerr = query.lastError().text();
        QMessageBox::critical(0, title,
                                 tr("Невозможно прочитать настройки БД.\n\r Причина: ")+qerr,
                                QMessageBox::Ok);
    }
    
    db_driver = query.value(0).toString();
    query.next();
    db_name = query.value(0).toString();
    query.next();
    db_user_name = query.value(0).toString();
    query.next();
    db_user_paswd = query.value(0).toString();
    
    db_main = QSqlDatabase::addDatabase(db_driver,"maindb");
    db_main.setDatabaseName(db_name);
    db_main.setUserName(db_user_name);
    db_main.setPassword(db_user_paswd);
qDebug() << "db_main.open: " << QDateTime::currentDateTime() << "\n\r";
    ok = db_main.open();
    
    if (!ok)
    {
        qerr = db_main.lastError().text();
        QMessageBox::critical(0, title,
                                 QObject::tr("Невозможно установить соединение c БД.\n\r")+qerr,
                                QMessageBox::Ok);
    }
qDebug() << "db_main.open: " << QDateTime::currentDateTime() << "\n\r";
qDebug() << db_main << "\n\r";
}

acen83 Дата 6.8.2008, 19:51
  2 Litkevich Yuriy:

clear() - возвращало бы все в начальное состояние, как при запуске программы.

Дело в том что после QSqlDatabase::removeDatabase("qt_default_connection_что_то_типа_этого") в списке соединений ничего нет. Т.е. базу мы закрыли, удалили соединение, а при запуске новой базы ругательство все равно остается - непорядок.

У меня при нажатии на кнопку происходит инициализация БД, настройка БД, выполнение запросов, закрытие всего этого хозяйства. Получается в разных частях программы надо создавать именованные соединения, причем вынесенные в конструктор? че то некрасиво как то, тем более вероятность нажатия кнопки - 1 к 100.
Litkevich Yuriy Дата 6.8.2008, 19:19
  во-первых, в программе работай по порядку, и давай имена соединениям. И по этим именам обращайся к соединению.
во-вторых, в Qt'ях работа идет с именоваными соединениями,
Цитата
Используйте contains(), чтобы видеть если заданное имя соединения в списке соединений

если нет то надо создать, а вообще удалять соединение, все-таки нужды нет.

Цитата(acen83 @ 6.8.2008, 22:41) *
функции наподобие clear() и соответственно isNull()

что должны были бы делать эти функции, еслиб они были?
Просмотр темы полностью (откроется в новом окне)
RSS Текстовая версия Сейчас: 29.3.2024, 18:31