Qt SQL连接即使在删除后仍处于打开状态

Qt SQL连接即使在删除后仍处于打开状态,qt,qt4,Qt,Qt4,第二次尝试连接到数据库时,我收到以下消息: QSqlDatabasePrivate::removeDatabase: connection 'CompanyDatabase' is still in use, all queries will cease to work. 我删除了以前使用过的模型,删除了所有连接,并关闭了数据库。下面,我将打开CompanyWidget的小部件作为一个模式对话框,因为我认为它可能与我如何打开/关闭使用数据库的小部件有关。有人能解释一下为什么这个数据库还在使用吗

第二次尝试连接到数据库时,我收到以下消息:

QSqlDatabasePrivate::removeDatabase: connection 'CompanyDatabase' is still in use, all queries will cease to work.
我删除了以前使用过的模型,删除了所有连接,并关闭了数据库。下面,我将打开CompanyWidget的小部件作为一个模式对话框,因为我认为它可能与我如何打开/关闭使用数据库的小部件有关。有人能解释一下为什么这个数据库还在使用吗

编辑:如果我将QSQLDABASE成员更改为指针并使用以下方法创建它:

this->CompanyDatabase = new QSqlDatabase(QSqlDatabase::addDatabase("QSQLITE", "CompanyDatabase"));
并在重新添加数据库之前将其删除:

  if(this->CompanyDatabase)
    {
    delete this->CompanyDatabase;
    this->CompanyDatabase = NULL;
    }
然后错误消失了。为什么这与我处理非指针成员的方式有什么不同

编辑公司Widget.h

#ifndef EditCompanyWidget_H
#define EditCompanyWidget_H

#include "ui_EditCompanyWidget.h"

#include <QDialog>
#include <QSqlDatabase>

class QSqlTableModel;


class EditCompanyWidget : public QDialog, private Ui::EditCompanyWidget
{
Q_OBJECT
public:

  EditCompanyWidget(QSqlDatabase);
  ~EditCompanyWidget();

public slots:

  void on_btnExit_clicked();

protected:
  QSqlTableModel* Model;
};

#endif
EditCompanyWidget.cpp

#include "EditCompanyWidget.h"

#include <iostream>

#include <QSqlDatabase>
#include <QStringList>
#include <QSqlQuery>
#include <QDebug>
#include <QSqlError>
#include <QVariant>
#include <QSqlTableModel>
#include <QSqlRecord>

EditCompanyWidget::EditCompanyWidget(QSqlDatabase database) : QDialog(NULL)
{
  setupUi(this);

  //QSqlTableModel* model = new QSqlTableModel;
  this->Model = new QSqlTableModel(NULL, database);
  this->Model->setTable("CompanyTable");
  this->Model->setEditStrategy(QSqlTableModel::OnManualSubmit);
  //model->setFilter(QString("id=%1").arg(1));
  this->Model->select();

  this->tableView->setModel(this->Model);
}

EditCompanyWidget::~EditCompanyWidget()
{
  if(this->Model)
    {
    std::cout << "destructor Deleting..." << std::endl;
    delete this->Model;
    this->Model = NULL;
    }
}


void EditCompanyWidget::on_btnExit_clicked()
{
  this->Model->revertAll();
  if(this->Model)
    {
    std::cout << "btnExit Deleting..." << std::endl;
    delete this->Model;
    this->Model = NULL;
    }
  //this->setResult(QDialog::Rejected);
  this->reject();
}
#include "TimeTrackerConfigurationWidget.h"

#include "EditCompanyWidget.h"

#include <iostream>

#include <QSqlDatabase>
#include <QFileDialog>
#include <QSqlError>
#include <QSqlQuery>

TimeTrackerConfigurationWidget::TimeTrackerConfigurationWidget(QWidget *parent) : QMainWindow(parent)
{
  setupUi(this);
}


void TimeTrackerConfigurationWidget::on_btnEditCompany_clicked()
{
//   QString fileName = QFileDialog::getOpenFileName(this, "Database File", ".", "Image Files (*.sqlite)");
//
//   if(fileName.toStdString().empty())
//     {
//     std::cout << "Filename was empty." << std::endl;
//     return;
//     }

  QString fileName = "test.sqlite";

  if(!QFile::exists(fileName))
    {
    std::cerr << "File does not exist!" << std::endl;
    return;
    }

  this->CompanyDatabase.close();
  //QSqlDatabase::removeDatabase("CompanyDatabase");
  //QSqlDatabase database = QSqlDatabase::addDatabase("QSQLITE");

  // Delete all connections
  for(unsigned int i = 0; i < QSqlDatabase::connectionNames().size(); ++i)
    {
    //QSqlDatabase::removeDatabase("TestConnection");
    QSqlDatabase::removeDatabase(QSqlDatabase::connectionNames()[i]);
    }


  this->CompanyDatabase = QSqlDatabase::addDatabase("QSQLITE", "CompanyDatabase");
  //this->CompanyDatabase = QSqlDatabase::addDatabase("QSQLITE");
  this->CompanyDatabase.setDatabaseName(fileName);
  if (!this->CompanyDatabase.open())
    {
    std::cerr << "Could not open database" << std::endl;
    std::cerr << this->CompanyDatabase.lastError().text().toStdString() << std::endl;
    return;
    }

  EditCompanyWidget* editCompanyWidget = new EditCompanyWidget(this->CompanyDatabase);
  editCompanyWidget->exec();
  delete editCompanyWidget;
}
MainWidget.h

#ifndef TimeTrackerConfigurationWidget_H
#define TimeTrackerConfigurationWidget_H

#include "ui_TimeTrackerConfigurationWidget.h"

#include <QMainWindow>
#include <QSqlDatabase>

class TimeTrackerConfigurationWidget : public QMainWindow, private Ui::TimeTrackerConfigurationWidget
{
Q_OBJECT
public:
  TimeTrackerConfigurationWidget(QWidget *parent = 0);

public slots:
  void on_btnNewCompany_clicked();
  void on_btnEditCompany_clicked();

protected:
  QSqlDatabase CompanyDatabase;
};

#endif
MainWidget.cpp

#include "EditCompanyWidget.h"

#include <iostream>

#include <QSqlDatabase>
#include <QStringList>
#include <QSqlQuery>
#include <QDebug>
#include <QSqlError>
#include <QVariant>
#include <QSqlTableModel>
#include <QSqlRecord>

EditCompanyWidget::EditCompanyWidget(QSqlDatabase database) : QDialog(NULL)
{
  setupUi(this);

  //QSqlTableModel* model = new QSqlTableModel;
  this->Model = new QSqlTableModel(NULL, database);
  this->Model->setTable("CompanyTable");
  this->Model->setEditStrategy(QSqlTableModel::OnManualSubmit);
  //model->setFilter(QString("id=%1").arg(1));
  this->Model->select();

  this->tableView->setModel(this->Model);
}

EditCompanyWidget::~EditCompanyWidget()
{
  if(this->Model)
    {
    std::cout << "destructor Deleting..." << std::endl;
    delete this->Model;
    this->Model = NULL;
    }
}


void EditCompanyWidget::on_btnExit_clicked()
{
  this->Model->revertAll();
  if(this->Model)
    {
    std::cout << "btnExit Deleting..." << std::endl;
    delete this->Model;
    this->Model = NULL;
    }
  //this->setResult(QDialog::Rejected);
  this->reject();
}
#include "TimeTrackerConfigurationWidget.h"

#include "EditCompanyWidget.h"

#include <iostream>

#include <QSqlDatabase>
#include <QFileDialog>
#include <QSqlError>
#include <QSqlQuery>

TimeTrackerConfigurationWidget::TimeTrackerConfigurationWidget(QWidget *parent) : QMainWindow(parent)
{
  setupUi(this);
}


void TimeTrackerConfigurationWidget::on_btnEditCompany_clicked()
{
//   QString fileName = QFileDialog::getOpenFileName(this, "Database File", ".", "Image Files (*.sqlite)");
//
//   if(fileName.toStdString().empty())
//     {
//     std::cout << "Filename was empty." << std::endl;
//     return;
//     }

  QString fileName = "test.sqlite";

  if(!QFile::exists(fileName))
    {
    std::cerr << "File does not exist!" << std::endl;
    return;
    }

  this->CompanyDatabase.close();
  //QSqlDatabase::removeDatabase("CompanyDatabase");
  //QSqlDatabase database = QSqlDatabase::addDatabase("QSQLITE");

  // Delete all connections
  for(unsigned int i = 0; i < QSqlDatabase::connectionNames().size(); ++i)
    {
    //QSqlDatabase::removeDatabase("TestConnection");
    QSqlDatabase::removeDatabase(QSqlDatabase::connectionNames()[i]);
    }


  this->CompanyDatabase = QSqlDatabase::addDatabase("QSQLITE", "CompanyDatabase");
  //this->CompanyDatabase = QSqlDatabase::addDatabase("QSQLITE");
  this->CompanyDatabase.setDatabaseName(fileName);
  if (!this->CompanyDatabase.open())
    {
    std::cerr << "Could not open database" << std::endl;
    std::cerr << this->CompanyDatabase.lastError().text().toStdString() << std::endl;
    return;
    }

  EditCompanyWidget* editCompanyWidget = new EditCompanyWidget(this->CompanyDatabase);
  editCompanyWidget->exec();
  delete editCompanyWidget;
}

文件中明确指出:。在删除连接之前,必须销毁所有已实例化的查询对象和QSqlDatabase连接对象。当您删除指针时,实际上就是这样做的。对于您以前的代码,您没有这样做。

对不起,我弄错了,我的badIt看起来非常奇怪,尽管您不能将对象保留为成员变量,然后对其调用某种断开连接函数来模拟删除它?这是一个问题还是一个陈述?对不起,我不知道有没有办法,但我认为没有必要。通过使用静态QSqlDatabase::database。。。你想做什么就做什么。也可以使用重写操作符=你可以分配给对象,而不是复制,我猜,所以没有开销。考虑一下这个错误。到处都有人问它,这里也有关于堆栈溢出的问题。您可能会找到更多信息。我想我不明白为什么必须使用静态函数添加和删除连接。如果您只需要使用诸如ConnectionObject myConnection=SqlDatabase之类的东西来控制连接,不是会容易得多吗?好吧,这取决于你。我觉得这样很好。但是你看过我最后的评论了吗?你就是这么做的。您添加了数据库。。要使用名称创建连接,您可以稍后使用数据库检索连接对象。。。方法:QSqlDatabase myConnection=QSqlDatabase::databaseconnectionName。。。您可以使用removeConnection删除连接。这怎么可能更简单呢?所有这些都在文档中用代码片段清楚地说明了。