简体   繁体   中英

Open and closing ODBC connections causing crashes

I wrote a program that used a SQLite database and it worked correctly. Now I'm trying to make it work with SQL Server. The application crashes on startup and I have worked out that it's to do with the way I am opening and closing database connections. I'm really unsure if I need to open the connection only once or if should I open and close it each time I run a query? Also is it advised to delete the pointer to the query after it executes? Removing the conn.connOpen and conn.connClose sections makes the program run, but its unstable.

Any advice on how to handle connections (since I have a lot of buttons that execute different queries) is greatly appreciated.

My connection string is stored in a header (mainwindow)

// mainwindows.h 

public:
QSqlDatabase mydb;
void connClose()
{
    connected = false;
    mydb.close();
    mydb.QSqlDatabase();
    mydb.removeDatabase(QSqlDatabase::defaultConnection);
}

bool connOpen()
{
    if( !connected )
    {
        mydb = QSqlDatabase::addDatabase("QODBC"); //uses dsn, connects fine. 
        mydb.setDatabaseName("Test");
        if(!mydb.open())
        {                    
            qDebug() << mydb.lastError().text();
            connected = false;
        }
        else
        {
            qDebug()<<"Connected";
            connected = true;
        }
    }
    return connected;
}

private:
static bool connected;

Here is an example of how I'm calling queries in my .cpp files;

Financelog::Financelog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Financelog)
{    
    ui->setupUi(this);
    setWindowFlags( windowFlags() | Qt::WindowMinimizeButtonHint | 
                    Qt::WindowContextHelpButtonHint | Qt::WindowMinMaxButtonsHint );

    MainWindow conn; // call the connection string
    if(!conn.connOpen())
        ui->label_sec_status->setText("<font color='red'>Failed to Open Database</font>"); 
    else
        ui->label_sec_status->setText("<font color='green'>Connected</font>");

    QSqlQueryModel * modal=new QSqlQueryModel();

    conn.connOpen(); // ---- **DO I NEED THIS? REMOVING STOPS CRASHES.** 

    QSqlQuery* qry=new QSqlQuery(conn.mydb);

    qry->prepare("select DEAL_DATE, DEAL_NUMB, CCICOMM, CCIPREM, INCOME from LOG");     
    qry->exec();
    modal->setQuery(*qry);
    ui->tableView->setModel(modal); 
    ui->tableView->resizeColumnsToContents();
    ui->tableView->setAlternatingRowColors(true);
    ui->tableView->setStyleSheet("alternate-background-color: #009900; background-color: #006600;");

    //delete qry;  **DO I NEED THIS TO RELEASE MEMORY?**

    conn.connClose(); // **DO I NEED THIS?** 

    qDebug() << (modal->rowCount());
}
  1. You should only open the connection once, and keep it open while using it. Not open and close for every query.
    • If you have long phases of nothing between 2 queries, you can use a QTimer to close the connection after beeing unused for a "long" time (eg 5 min). Do so if you see the connection timing out. But by default, not needed.
  2. QSqlQuery , just like QSqlDatabase should be used as "value class", not as a pointer (See Qt Documentation ). Instead of creating one with new , create it on the stack. Queries are copyable.

Code sample:

//only once, i.e. in your windows constructor
conn.connOpen();

//set up the model
QSqlQueryModel * modal=new QSqlQueryModel();

QSqlQuery qry(conn.mydb);

qry.prepare("...");     
qry.exec();
modal->setQuery(qry);
//...

// do not delete the query or close the database connection!

qDebug() << (modal->rowCount());

You can close the connection in the destructor after the model has been destroyed:

model->deleteLater();
conn.connClose();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM