.net/c#アプリケーションをQtに変換する処理中です。私は毎日Qt/C++で動作しませんので、私に同行してください。Qt - 複数のデータベース接続を同時に処理する
アプリケーションはSQLiteとMS SQL Serverを同時に使用します。接続が確立されると、両方のデータストアでデータトランザクションが非常に高く、トランザクション間の接続の開閉時間を無駄にしたくないため、オープンにしています。
私の目的は、両方のデータベースタイプに使用できる汎用マネージャクラスを作成することでした。いずれかの接続が他の接続なしで開かれている場合、クラスは正常に動作します。ただし、同時に両方の接続を確立しようとすると、エラーが発生します。
QSqlDatabasePrivate :: removeDatabase:接続 'qt_sql_default_connection'は引き続き使用され、すべてのクエリが機能しなくなります。
QSqlDatabasePrivate :: addDatabase:接続名 'qt_sql_default_connection'が重複し、古い接続が削除されました。
だから、私は約connection namingを読んだ。しかし、次にデータベースにアクセスする際の問題にぶつかる。私は接続名を付けずに自分のデータベースマネージャークラスの内容を投稿しました。私は、これをきれいで一般的な方法でどのように扱うべきかに関する提案を探しています。ありがとう!
.hファイル以下
#ifndef DATABASEMGR_H
#define DATABASEMGR_H
#include <QObject>
#include <QSqlDatabase>
#include <QVariant>
#include <QSqlQuery>
#include <QSqlQueryModel>
#include <QSqlRecord>
class DatabaseMgr : public QObject
{
public:
DatabaseMgr(const QString &databaseType, const QString &connectionString, QObject *parent = 0);
~DatabaseMgr();
QVariant ExecuteScalar(const QString &cmd);
bool ExecuteNonQuery(const QString &cmd);
bool IsOpen() const;
bool Connect();
bool Disconnect();
QSqlQueryModel *GetQueryModel(const QString &cmd);
QSqlQueryModel *GetQueryModel(const QString &cmd, const QMap<QString, QVariant> ¶ms);
private:
QSqlDatabase mDb;
};
#endif // DATABASEMGR_H
の.cpp
#include "databasemgr.h"
DatabaseMgr::DatabaseMgr(const QString &databaseType, const QString &connectionString, QObject *parent) {
mDb = QSqlDatabase::addDatabase(databaseType);
mDb.setDatabaseName(connectionString);
}
DatabaseMgr::~DatabaseMgr() {
if (mDb.open()) {
mDb.close();
}
}
QVariant DatabaseMgr::ExecuteScalar(const QString &cmd) {
QVariant mVariant;
if (mDb.isOpen()) {
QSqlQuery query;
if (query.exec(cmd)) {
while (query.next()) {
mVariant = query.value(0);
}
}
}
return mVariant;
}
bool DatabaseMgr::ExecuteNonQuery(const QString &cmd) {
if (mDb.isOpen()) {
QSqlQuery query;
if (query.exec(cmd)) {
return true;
} else {
//todo handle error
}
} else {
//todo handle error
}
return false;
}
bool DatabaseMgr::IsOpen() const {
return mDb.isOpen();
}
bool DatabaseMgr::Connect(){
if (!mDb.open()) {
//todo error opening database??
return false;
}
return true;
}
bool DatabaseMgr::Disconnect() {
return mDb.isOpen();
}
QSqlQueryModel *DatabaseMgr::GetQueryModel(const QString &cmd) {
QSqlQueryModel *model = new QSqlQueryModel;
if (mDb.isOpen()) {
model->setQuery(cmd, mDb);
}
return model;
}
QSqlQueryModel *DatabaseMgr::GetQueryModel(const QString &cmd, const QMap<QString, QVariant> ¶ms) {
QSqlQueryModel *model = new QSqlQueryModel;
if (mDb.isOpen()) {
QSqlQuery query;
query.prepare(cmd);
if (params.count() > 0) {
QMapIterator<QString, QVariant> i(params);
while (i.hasNext()) {
i.next();
query.bindValue(i.key(), i.value());
}
}
model->setQuery(query);
}
return model;
}
例の用途:
main.cppに(SQLiteのDBがグローバル・アプリケーションを格納するために使用されています設定)
プログラムのメンバ関数内からDatabaseMgr mSqliteDb("QSQLITE", app.applicationName() + ".db", &app);
mSqliteDb.Connect();
Program prgm(mSqliteDb, &app);
program.cpp
mMsSqlDb = new DatabaseMgr("QODBC3", GetMsSqlConnectionString());
if (mMsSqlDb->Connect()) {
AddToActivityLog("Connected to MS SQL DB");
} else {
AddToActivityLog("Error connecting to MS SQL DB");
}
の取得結果:
QString cmd = "SELECT DISTINCT some_things FROM the_table ORDER BY these_columns";
QSqlQueryModel *model = mMsSqlDb->GetQueryModel(cmd);
if (model->rowCount() > 0) {
for (int i = 0; i < model->rowCount(); ++i) {
//Do stuff...
}
}
2つのデータベースのための2つのオブジェクトを作成するには、このクラスを使用しているご提示ください。私は問題なくMySQLとSQLiteでこれを行いました。 –
上記のポストされた例を参照して、私はプログラム内でマネージャクラスのインスタンスを2つ作成しました.1つはsqlite用、もう1つはms sql用です。 sqliteインスタンスは参照渡しされ、アプリケーションを持つすべてのクラスで使用できます。 ms sqlインスタンスは、プログラムクラス内のプライベートメンバポインタです。インスタンス化と接続の後、私はその時必要なDBマネージャークラスの公開関数を呼び出します。つまり、レコードの更新、レコードの取得などです。 – DonJoe
コードと私の違いは、接続名で送信したことです。 myDB = QSqlDatabase :: addDatabase(databaseType、connectionName);私はこれがあなたの問題に対処するかもしれないと思います。 (dbごとに異なる接続名) –