QSqlDatabase und Multithreading

Alles rund um die Programmierung mit Qt
Antworten
Willi2793
Beiträge: 147
Registriert: 29. September 2008 10:59
Kontaktdaten:

QSqlDatabase und Multithreading

Beitrag von Willi2793 »

Hallo,

ich weiß das das Thema schon öfter behandelt wurde. Aber irgendwie konnte ich die Information die ich gerne hätte nicht finden. Ich stelle mir folgende Klasse vor:

Code: Alles auswählen

QAtomicInt SQLClass::reference = QAtomicInt(0);
QString SQLClass::cConnectionName = "ConnectionName";

SQLClass::SQLClass()
{
    SQLClass::reference.ref();
    QSqlDatabase::database(SQLClass::cConnectionName, false).open();
}

SQLClass::SQLClass(const IniFile& iniFile, const QString& cSection)
{
    SQLClass::reference.ref();
    if (!QSqlDatabase::database(SQLClass::cConnectionName, false).isValid()) {
        QSqlDatabase database  = QSqlDatabase::addDatabase("QODBC", SQLClass::cConnectionName);
        QString server = iniFile.getString(cSection,"SERVER");
        database.setDatabaseName("DRIVER=" + iniFile.getString(cSection,"DRIVER") + ";DATABASE=" + iniFile.getString(cSection,"DATABASE") + ";SERVER=" + server);
        database.setHostName(server);
        database.setUserName(iniFile.getString(cSection,"USER","",true));
        database.setPassword(iniFile.getString(cSection,"PASS","",true));
        SQLClass::nLog = iniFile.getString(cSection,"LOG","0").toInt(NULL);
    } else {
        log("Init of SQLDatabase was wrong",1);
    }
    QSqlDatabase::database(SQLClass::cConnectionName, false).open();
}

SQLClass::~SQLClass()
{
    QSqlDatabase::database(SQLClass::cConnectionName, false).close();
    if (!SQLClass::reference.deref()) {
        QSqlDatabase::removeDatabase(SQLClass::cConnectionName);
    } else {
    }
}

bool SQLClass::execute(const QString& cStmt) {
    .
    .
    .
    .
    return lResult;
}
Dieses Grundgerüst wird am Anfang des Programmes mit dem CTR mit den beiden parametern aufgerufen und somit ein Connection erstellt. Ich stelle mir dann vor das diese Klasse später im Programm und auch in anderen Threads immer wieder ohne Parameter konstruiert wird. Ist das ein denkbares und korrrektes Vorgehen?

Viele Grüße,
Willi
Willi2793
Beiträge: 147
Registriert: 29. September 2008 10:59
Kontaktdaten:

Beitrag von Willi2793 »

Ich würde das gerne nochmal nach oben schieben
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

Ich halte ein solches "ConnectionManagement" für sinnvoll, sehe jedoch in diesem konkreten Code folgende Probleme:

1. open/close
In meiner Implementierung öffnet die erste Instanz die Verbindung (open()), die letzte Instanz schliesst sie wieder (close()) und alle dazwischen testen sie (if (!db.isOpen()) db.open()). Dein mehrfaches open() (im CTor) und close() (im DTor) halt ich nicht für richtig.

2. Multithreading
In der Doku steht klar: "A connection can only be used from within the thread that created it". Das ist bei dir nicht der Fall. Du hast für alle Threads nur _eine_ Connection. Richtig wäre IMHO, dass dein Management abhängig des "QThread::currentThread()" Connections generiert. Also kannst du keine Konstante für den ConnectionName nehmen, sonder was vom Thread abhängiges. Auch das Reference-Counting müsste natürlich abhängig des Threads funktionieren.
Zusammengefasst: verwalte eine Liste von Connections, nicht _eine_ Connection.
Willi2793
Beiträge: 147
Registriert: 29. September 2008 10:59
Kontaktdaten:

Beitrag von Willi2793 »

solarix hat geschrieben:1. open/close
In meiner Implementierung öffnet die erste Instanz die Verbindung (open()), die letzte Instanz schliesst sie wieder (close()) und alle dazwischen testen sie (if (!db.isOpen()) db.open()). Dein mehrfaches open() (im CTor) und close() (im DTor) halt ich nicht für richtig.
Da dachte ich das eventuell timeouts ansonsten das clsoe() implizit machen und man dann Probeme bekommt. Deshalb das open() jedesmal. Ist das also nicht okay?
solarix hat geschrieben:2. Multithreading
...
Danke, das leuchtet mir dann ein.
Antworten