如何和数据库保持连接状态?

时间:2021-12-16 11:34:13
日前写了一个程序,里面用了一个ADOQUERY。第一次和写入数据时,程序运行很慢,大概10分钟才能把数据写进去。不过下面就好多了,数据马上就能写到数据库。应该如何解决这样的问题? 

当把和数据库服务器网络中断又恢复连接后,刷卡依然说不能和数据库连接。而此时网络已经连通。重新把程序运行就没有问题。应该如何做,才能在网络恢复连接后让程序也能和数据库连接上? 

怎么检测和数据库是否连接状态,当和远程数据库失去连接时,自动把数据保存在本地,等网络连接恢复后,把数据送到远程数据库?

7 个解决方案

#1


第一种现象,我想应该是你的程序问题,把代码贴出来大家看看

第二种:网络中断后,与数据库的连接肯定也断了,重新连接后,网络是通了,可你的程序没有和数据库重新连接,要恢复的话重新Open()就可以了

第三种:你把你的连接数据库的代码用try catch包起来。连接不上的话肯定会抛出异常的。
但失去连接了再保存数据是不可能的,除非在没中断前把数据保存。“把数据送到远程数据库?”这句话我不明白什么意思。。

#2


是一个员工考勤刷卡的简单程序。
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "MainForm.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "cxControls"
#pragma link "dxLayoutControl"
#pragma link "dxCntner"
#pragma link "dxEdLib"
#pragma link "dxExEdtr"
#pragma link "dxDBELib"
#pragma link "dxEditor"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
        //获得数据库连接字段
        HINSTANCE Dll=NULL;
        Dll=LoadLibrary("Dll\\DB.dll");
        typedef AnsiString (__import  GetConnStringType)(void) ;
        GetConnStringType * GetConnString;
        if (Dll)
                {
                GetConnString=(GetConnStringType *)GetProcAddress(Dll,"_ConnString");
                if(GetConnString)
                         {
                         Connection=GetConnString();
                         }
                }
        else
               ShowMessage(SysErrorMessage(GetLastError()));

        //初始化数据库组件
        ADOQuery1->ConnectionString=Connection;
        //释放DB.Dll
        FreeLibrary(Dll);
        //使input获得焦点

//Input TEdit
        Input->Focused();
        Input->Clear();

        Label2->Caption="请刷卡";
        Label3->Caption="";
        time->Caption=TimeToStr(Now());
        date->Caption=DateToStr(Now());

}
//---------------------------------------------------------------------------                     

//---------------------------------------------------------------------------



void __fastcall TForm1::InputKeyPress(TObject *Sender, char &Key)
{
        if(Key=='\r')
                {
                int count;
                AnsiString EmpID;
                InputCardNo=Input->Text;
                Input->Clear();
                LastTime=Now();

                
                ADOQuery3->ConnectionString=Connection;
                ADOQuery3->SQL->Clear();
                ADOQuery3->SQL->Add("select * from card where CardNo='"+InputCardNo+"'");
                //ShowMessage(ADOQuery3->SQL->Text);
                ADOQuery3->Open();
                ADOQuery3->Edit();
                ADOQuery3->ExecSQL();

                count=ADOQuery3->RecordCount;
                //获得员工id : EmpID
                if(count==1)
                        EmpID=ADOQuery3->FieldByName("EmpID")->AsString;
                ADOQuery3->Close();


                if (count==1)
                        {

//Tperson表中,fno为员工id
                        AnsiString SQLString;
                        SQLString="select fno,fname,case fsex when '1' then '男' when '2' then '女' end fsex from tperson where fno='"
                                +EmpID+"'" ;
                        ADOQuery1->SQL->Clear();
                        ADOQuery1->SQL->Add(SQLString);
                        ADOQuery1->Open();
                        ADOQuery1->Edit();
                        ADOQuery1->Post();
                        
                        Label2->Caption="刷卡成功";
                        Label3->Caption="刷卡时间"+TimeToStr(LastTime.Val);;
                        ADOQuery2->ConnectionString=Connection;
                        ADOQuery2->SQL->Clear();
                        ADOQuery2->SQL->Add("select * from record");
                        //ADOQuery2->SQL->Add("insert into Record (CardNo,RecordTime,Property) values ('"+Input->Text+"','"+Now()+"','Auto' )");
                        //ShowMessage(ADOQuery2->SQL->Text);
                        ADOQuery2->Active=true;
                        ADOQuery2->Append();
                        ADOQuery2->FieldValues["CardNo"]=InputCardNo;
                        ADOQuery2->FieldValues["RecordTime"]=LastTime;
                        ADOQuery2->FieldValues["Property"]="Auto";
                        ADOQuery2->Post();
                        ADOQuery2->Close();
                        dxGraphicEdit1->Picture->LoadFromFile("FACE.ICO");
                        dxGraphicEdit1->Visible=true;
                        }
                else
                        {
                        dxGraphicEdit1->Picture->LoadFromFile("YIELD.ICO");
                        dxGraphicEdit1->Visible=true;
                        Label2->Caption="请刷卡";
                        Label3->Caption="";
                        Input->Clear();
                        }
                }


}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
//10秒钟刷新一次界面
        if (Now().Val -LastTime>10.0/24/60/60)
                {
                 
                 ADOQuery1->Close();
                 Label2->Caption="请刷卡";
                 Label3->Caption="";

                 dxGraphicEdit1->Visible=false;
                }
        
        time->Caption=TimeToStr(Now());
        date->Caption=DateToStr(Now());
        Input->Focused();

}
//---------------------------------------------------------------------------


void __fastcall TForm1::InputExit(TObject *Sender)
{
        Input->SetFocus();        
}
//---------------------------------------------------------------------------


void __fastcall TForm1::FormActivate(TObject *Sender)
{
        Input->SetFocus();
        dxGraphicEdit1->Visible=false;
}
//---------------------------------------------------------------------------


2.我每次获得数据都重新用open()了啊。

3.我的意思是,在保存数据前,先检测网络是否连通。如果不通就直接保存到本地。如果连通的话,就保存到远程数据库。因为不能让网络故障而影响到员工的正常考勤。

#3


看你的应用,如果简单的话,可以直接保存数据在本机Access中,需要时(例如每隔10分钟),和远程数据库连接,如果连接得上就把本机未拷贝的数据简单的添加到远程机。

#4


判断远程数据库是否能正常连接可以用
try
{
     ADOConnection->Connected =true;
     //成功
}
catch(...)
{
     //失败
}

但如果网络不通,这里会阻塞很久,解决的方法可以另开一个线程。

#5


简单看了一下代码,好像没有多大问题,网络中断后你仔细跟踪一下,看看到底是哪个地方出问题了,应该能查到的

#6


对了,建议你先
Close()

Clear()

Add()

Open()
我怀疑是你没有先Close()的原因导致连接不上

#7


先Close();

#1


第一种现象,我想应该是你的程序问题,把代码贴出来大家看看

第二种:网络中断后,与数据库的连接肯定也断了,重新连接后,网络是通了,可你的程序没有和数据库重新连接,要恢复的话重新Open()就可以了

第三种:你把你的连接数据库的代码用try catch包起来。连接不上的话肯定会抛出异常的。
但失去连接了再保存数据是不可能的,除非在没中断前把数据保存。“把数据送到远程数据库?”这句话我不明白什么意思。。

#2


是一个员工考勤刷卡的简单程序。
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "MainForm.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "cxControls"
#pragma link "dxLayoutControl"
#pragma link "dxCntner"
#pragma link "dxEdLib"
#pragma link "dxExEdtr"
#pragma link "dxDBELib"
#pragma link "dxEditor"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
        //获得数据库连接字段
        HINSTANCE Dll=NULL;
        Dll=LoadLibrary("Dll\\DB.dll");
        typedef AnsiString (__import  GetConnStringType)(void) ;
        GetConnStringType * GetConnString;
        if (Dll)
                {
                GetConnString=(GetConnStringType *)GetProcAddress(Dll,"_ConnString");
                if(GetConnString)
                         {
                         Connection=GetConnString();
                         }
                }
        else
               ShowMessage(SysErrorMessage(GetLastError()));

        //初始化数据库组件
        ADOQuery1->ConnectionString=Connection;
        //释放DB.Dll
        FreeLibrary(Dll);
        //使input获得焦点

//Input TEdit
        Input->Focused();
        Input->Clear();

        Label2->Caption="请刷卡";
        Label3->Caption="";
        time->Caption=TimeToStr(Now());
        date->Caption=DateToStr(Now());

}
//---------------------------------------------------------------------------                     

//---------------------------------------------------------------------------



void __fastcall TForm1::InputKeyPress(TObject *Sender, char &Key)
{
        if(Key=='\r')
                {
                int count;
                AnsiString EmpID;
                InputCardNo=Input->Text;
                Input->Clear();
                LastTime=Now();

                
                ADOQuery3->ConnectionString=Connection;
                ADOQuery3->SQL->Clear();
                ADOQuery3->SQL->Add("select * from card where CardNo='"+InputCardNo+"'");
                //ShowMessage(ADOQuery3->SQL->Text);
                ADOQuery3->Open();
                ADOQuery3->Edit();
                ADOQuery3->ExecSQL();

                count=ADOQuery3->RecordCount;
                //获得员工id : EmpID
                if(count==1)
                        EmpID=ADOQuery3->FieldByName("EmpID")->AsString;
                ADOQuery3->Close();


                if (count==1)
                        {

//Tperson表中,fno为员工id
                        AnsiString SQLString;
                        SQLString="select fno,fname,case fsex when '1' then '男' when '2' then '女' end fsex from tperson where fno='"
                                +EmpID+"'" ;
                        ADOQuery1->SQL->Clear();
                        ADOQuery1->SQL->Add(SQLString);
                        ADOQuery1->Open();
                        ADOQuery1->Edit();
                        ADOQuery1->Post();
                        
                        Label2->Caption="刷卡成功";
                        Label3->Caption="刷卡时间"+TimeToStr(LastTime.Val);;
                        ADOQuery2->ConnectionString=Connection;
                        ADOQuery2->SQL->Clear();
                        ADOQuery2->SQL->Add("select * from record");
                        //ADOQuery2->SQL->Add("insert into Record (CardNo,RecordTime,Property) values ('"+Input->Text+"','"+Now()+"','Auto' )");
                        //ShowMessage(ADOQuery2->SQL->Text);
                        ADOQuery2->Active=true;
                        ADOQuery2->Append();
                        ADOQuery2->FieldValues["CardNo"]=InputCardNo;
                        ADOQuery2->FieldValues["RecordTime"]=LastTime;
                        ADOQuery2->FieldValues["Property"]="Auto";
                        ADOQuery2->Post();
                        ADOQuery2->Close();
                        dxGraphicEdit1->Picture->LoadFromFile("FACE.ICO");
                        dxGraphicEdit1->Visible=true;
                        }
                else
                        {
                        dxGraphicEdit1->Picture->LoadFromFile("YIELD.ICO");
                        dxGraphicEdit1->Visible=true;
                        Label2->Caption="请刷卡";
                        Label3->Caption="";
                        Input->Clear();
                        }
                }


}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
//10秒钟刷新一次界面
        if (Now().Val -LastTime>10.0/24/60/60)
                {
                 
                 ADOQuery1->Close();
                 Label2->Caption="请刷卡";
                 Label3->Caption="";

                 dxGraphicEdit1->Visible=false;
                }
        
        time->Caption=TimeToStr(Now());
        date->Caption=DateToStr(Now());
        Input->Focused();

}
//---------------------------------------------------------------------------


void __fastcall TForm1::InputExit(TObject *Sender)
{
        Input->SetFocus();        
}
//---------------------------------------------------------------------------


void __fastcall TForm1::FormActivate(TObject *Sender)
{
        Input->SetFocus();
        dxGraphicEdit1->Visible=false;
}
//---------------------------------------------------------------------------


2.我每次获得数据都重新用open()了啊。

3.我的意思是,在保存数据前,先检测网络是否连通。如果不通就直接保存到本地。如果连通的话,就保存到远程数据库。因为不能让网络故障而影响到员工的正常考勤。

#3


看你的应用,如果简单的话,可以直接保存数据在本机Access中,需要时(例如每隔10分钟),和远程数据库连接,如果连接得上就把本机未拷贝的数据简单的添加到远程机。

#4


判断远程数据库是否能正常连接可以用
try
{
     ADOConnection->Connected =true;
     //成功
}
catch(...)
{
     //失败
}

但如果网络不通,这里会阻塞很久,解决的方法可以另开一个线程。

#5


简单看了一下代码,好像没有多大问题,网络中断后你仔细跟踪一下,看看到底是哪个地方出问题了,应该能查到的

#6


对了,建议你先
Close()

Clear()

Add()

Open()
我怀疑是你没有先Close()的原因导致连接不上

#7


先Close();