PDA

View Full Version : QSqlDatabase, removeDatabase



mustermann.klaus@gmx.de
12th May 2019, 19:00
Dear All,

I come back to a very popular error-message. I tried out a lot. I RTFM. I have no clue how to avoid the following mesage if dataGrabber is destrouyed.



QSqlDatabasePrivate::removeDatabase: connection 'qt_sql_default_connection' is still in use, all queries will cease to work.




class dataGrabber : public QObject
{
Q_OBJECT
public:
explicit dataGrabber(QObject *parent = nullptr);
~dataGrabber();

private:
QSqlDatabase dB;
QSqlQuery *query;

public slots:
bool openDatabase();
bool closeDatabase();
}




bool dataGrabber::openDatabase(){

dB = QSqlDatabase::addDatabase("QODBC");
dB.setHostName("localhost");
dB.setDatabaseName("DRIVER={Microsoft Access Driver (*.mdb)};FIL={MS Access};"
"DSN='';DBQ=" + dbPath + ";");

if(dB.open()){
query = new QSqlQuery(dB); // open dB and prepare query
prepareQuery();
return true;
{
else{
QMessageBox::warning(0, "Failure !", dB.lastError().text(), "OK");
return false;
}

return true;
}




bool dataGrabber::closeDatabase(){

query->finish();
query->clear();

delete query;

dB.close();

return true;
}




dataGrabber::~dataGrabber(){

dB.removeDatabase("qt_sql_default_connection");
}



As always, every help highly appreciated.

Cheers and thanks.

ChristianEhrlicher
12th May 2019, 19:50
See https://doc.qt.io/qt-5/qsqldatabase.html#removeDatabase - there is still a reference in your member 'QSqlDatabase dB;'

mustermann.klaus@gmx.de
13th May 2019, 08:16
Thanks ChristianEhrlicher


there is still a reference in your member 'QSqlDatabase dB;'

Yes, that's why it fails. But I do not get it. The tutorial (which I read) says to leave the function containing dB for the object to be destroyed and then call dB.removeDatabase(). How can I call something on a destroyed object?
Or am I completely mislead here?

anda_skoa
13th May 2019, 08:51
How can I call something on a destroyed object?


QSqlDatabase::removeDatabase() is a static method, just like QSqlDatabase::addDatabase().


So that would probably look similar to this


const QString connectionName = db.connectionName();
db = QSqlDatabase();
QSqlDatabase::removeDatabase(connnectionName);


Cheers,
_

mustermann.klaus@gmx.de
13th May 2019, 19:48
Okay, but I know the connectionName.



dB.removeDatabase("qt_sql_default_connection");


I understand why but really stucked on the question from where to call that ominous removeDatabase()

Cheers, Lars

ChristianEhrlicher
13th May 2019, 20:10
Simply ise the code from anda_skoa ...

mustermann.klaus@gmx.de
16th May 2019, 17:08
If it's that easy...Now it looks like this:



dataGrabber::~dataGrabber(){

const QString connectionName = dB.connectionName();
dB = QSqlDatabase();
dB.removeDatabase(connectionName);
}


Somehow I do not believe that I remove the right dB from the list. Do I?
The errormessage is gone. But dB is still a member of my class datagrabber, which I simply overwrite with an invalid object. I really do not understand, if this is the way, why I should do so.

greetingd from rainy Berlin, Lars

ChristianEhrlicher
17th May 2019, 06:27
That' not the code anda_skoa wrote for you... and why it has to be done that way was explicitly written in the documentation I gave you the link to - db holds a reference which also needs to be removed *before* QSqlDatabase::removeDatabase() is called.

anda_skoa
17th May 2019, 16:03
Somehow I do not believe that I remove the right dB from the list. Do I?

Why would it not be the right one?

Aside from not calling the static method as usual with "ClassName::methodName" this is passing the connection name of the "db" object you have been using.
Which, I assume, is the one you would want to remove.



But dB is still a member of my class datagrabber, which I simply overwrite with an invalid object.

Since "dB" is not a pointer, the only way to make it drop its connection is by invalidating it through overwriting.

Cheers,
_

mustermann.klaus@gmx.de
17th May 2019, 16:47
Hello everybody. Thanks for guiding me. To me it still seems confusing that an object has no method to end a connection to the world without beeing destroyed. But if so, I'll take it.



dataGrabber::~dataGrabber(){

const QString connectionName = dB.connectionName();
dB = QSqlDatabase();
QSqlDatabase::removeDatabase(connnectionName);
}


Works fine. Thank you.

Lars

tuli
20th May 2019, 13:28
I think QSqlDatabase is designed to be used in a more ad-hoc way, not as member variable perhaps.


Either way doing dB->close() seems cleaner to me?

mustermann.klaus@gmx.de
20th May 2019, 15:15
I think QSqlDatabase is designed to be used in a more ad-hoc way, not as member variable perhaps.


Either way doing dB->close() seems cleaner to me?

I think so too (in the meantime). As you can see in my initial post: dB->close(); is what I did in first sight.

Cheers.