如果数据库可访问,如何快速检查?(Qt、QML、C+;+;)-Linux 我使用QML和QML和C++。在我的应用程序中,我使用数据库。 如果数据库是可访问的,那么所有这些都可以工作

如果数据库可访问,如何快速检查?(Qt、QML、C+;+;)-Linux 我使用QML和QML和C++。在我的应用程序中,我使用数据库。 如果数据库是可访问的,那么所有这些都可以工作,c++,linux,database,qt,qml,C++,Linux,Database,Qt,Qml,我的问题是,我想检查数据库是否可以访问(比如ping) 我试过了 db.setDatabaseName(dsn); if(db.isValid()) { if(db.open()) { //std::cout <<"Offene Datenbank"; connected=true; } else { co

我的问题是,我想检查数据库是否可以访问(比如ping)

我试过了

    db.setDatabaseName(dsn);
    if(db.isValid())
    {

        if(db.open())
        {
            //std::cout <<"Offene Datenbank";
            connected=true;

        }
        else
        {
            connected=false;
        }


    }
    else
    {
        connected=false;
    }
db.setDatabaseName(dsn);
if(db.isValid())
{
if(db.open())
{

//std::cout我已经研究了这个问题。以下是我发现的

问题在于默认的数据库连接超时时间太长。每个数据库都允许您使用自己的API将其更改为可接受的值。在Qt中,有一个通用的数据库接口-
QSqlDatabase
。它没有这样的方法。您可以通过调用它的
QSqlDatabase::setConnectOptions
方法来设置连接设置,但它只接受预定义的选项列表(您可以在Qt的帮助中阅读)

对于
PostgreSQL
有一个选项
connect\u timeout
,因此您可以编写:

db.setConnectOptions("connect_timeout=5"); // Set to 5 seconds
对于其他数据库,没有这样的参数。每个数据库的连接选项在其“驱动程序”类中解析,该类派生
QSqlDriver
,并存储在“驱动程序”库中

那么,您可以做什么:

  • 您可以重写数据库的驱动程序,使其接受超时选项
  • 您可以使用每个数据库的本机API为其编写单独的代码
  • 更新

    事实证明,
    ODBC
    具有
    SQL\u ATTR\u CONNECTION\u TIMEOUT
    选项

    更新2

    qsql_odbc.cpp:713

    SQL属性连接超时(ODBC 3.0)

    SQLUINTEGER值 对应于服务器上等待任何请求的秒数 返回应用程序之前要完成的连接。驱动程序 应在任何时候返回SQLSTATE HYT00(超时过期) 可能在与查询无关的情况下超时 执行或登录

    如果ValuePtr等于0(默认值),则没有超时


    应该可以正常工作…

    我建议使用一些单独的线程/类,在其中检查连接,并在超时后发出信号,如果什么也没有发生(使用check-knowConnection,如果我们已经发现它是否已连接)。 这段代码不是从头开始测试和编写的。可能包含一些错误

    /// db connection validator in separate thread
    void validator::doValidate() {
     this->knowConnection = false;
     db.setDatabaseName(dsn);
     if(db.isValid())
     {
         QTimer::singleShot(1000, [this]() { 
             if (!this->knowConnection) {
                 emit connected(false);dm->connected=false;
             }
         });
         if(db.open())
         {
             //std::cout <<"Offene Datenbank";
             this->knowConnection = true;
             dm->connected=true;
             emit connected(true);
         }
         else
         {
             dm->connected=false;
             this->knowConnection = true;
             emit connected(false);
         }
     } 
     else
     {
         dm->connected=false;
         this->knowConnection = true;
         emit connected(false);
     }
    }
    
    /// db manager in different thread
    void dm::someDbFunction() {
        if (connected) {
            /// db logic
        }
    }
    
    /// in gui or whatever
    MainWindow::MainWindow() : whatever, val(new validator(..), .. {      
        connect(val, SIGNAL(connected(bool)), this, SLOT(statusSlot(bool));
        ....
    }
    
    void MainWindow::statusSlot(bool connected) {
        ui->statusBar->setText((connected?"Connected":"Disconnected"));
    }
    
    ///db连接验证程序位于单独的线程中
    void验证器::doValidate(){
    此->knowConnection=false;
    db.setDatabaseName(dsn);
    if(db.isValid())
    {
    QTimer::singleShot(1000,[this](){
    如果(!this->knowConnection){
    发射已连接(false);dm->connected=false;
    }
    });
    if(db.open())
    {
    //std::cout connected=true;
    发射连接(真);
    }
    其他的
    {
    dm->connected=false;
    此->knowConnection=true;
    发射连接(假);
    }
    } 
    其他的
    {
    dm->connected=false;
    此->knowConnection=true;
    发射连接(假);
    }
    }
    ///不同线程中的数据库管理器
    void dm::someDbFunction(){
    如果(已连接){
    ///数据库逻辑
    }
    }
    ///用图形用户界面或者别的什么
    MainWindow::MainWindow():无论如何,val(新验证器(…),…{
    连接(val,信号(已连接(bool)),此,插槽(状态插槽(bool));
    ....
    }
    void主窗口::状态插槽(bool已连接){
    ui->statusBar->setText((已连接?“已连接”:“已断开”);
    }
    
    我认为一个简单的解决方案是只检查数据库服务器的ping。您可以使用特定于平台的方式进行ping

    这将在Linux上工作:

    int exitCode = QProcess::execute("ping", QStringList() << "-c 2" << serverIp);
    if (exitCode==0) 
    {
        // is reachable
    } else 
    {
        // is not reachable
    }
    

    int-exitCode=QProcess::execute(“ping”,QStringList())“可访问”是指是否要检查文件是否已创建?或者您是否具有正确的权限?或者两者都有?我想知道,我是否可以像ping一样访问服务器。由于我在服务器上的配置文件,如果我可以访问服务器ip,我应该写/读。如果我无法访问数据库服务器,应用程序应该返回false,如果我无法访问数据库服务器,则返回true如果我可以访问它或连接到一个odbc驱动程序,那么我应该选择SQL\u ATTR\u CONNECTION\u TIMEOUT,当然?好吧,这很尴尬。我从来没有使用过odbc,所以我没有检查它的连接选项。是的,我想你是对的-
    SQL\u ATTR\u CONNECTION\u TIMEOUT
    正是你需要的。嗯,我在代码中使用了它,但这不起作用比以前更快设置了什么值?db.setConnectOptions(“SQL\u ATTR\u CONNECTION\u TIMEOUT=5;SQL\u ATTR\u LOGIN\u TIMEOUT=5”);if(db.open()){connected=true;}else{connected=false;}singleshot计时器在一个间隔后中止。但是我在拍摄一个时没有问题。问题是延迟时间太长,如果我理解你的意思..现在延迟为1秒,之后如果db.open()中没有任何事情发生,singleshot将发出我们没有连接的信号。如果你有连接,我假设db.open()立即返回(从而将knowConnection设置为true等)?嗯..所以计时器只工作一次..我会考虑一下。默认超时时间长的原因是在某些情况下连接到数据库可能需要很长时间。我曾经在一个有许多远程数据库服务器的项目上工作。我们的典型连接时间是7秒。有时更长,但很少,如果更短的话。这是值得衡量的您的连接时间和相应调整一次触发的长度,如果您使用此实现。我认为这可以与给出的其他答案结合使用。如果您不能ping服务器,您肯定无法建立连接。ping会快速返回该信息。
    int exitCode = QProcess::execute("ping", QStringList() << "-c 2" << serverIp);
    if (exitCode==0) 
    {
        // is reachable
    } else 
    {
        // is not reachable
    }