ado字段更新并写入数据库表的问题

时间:2022-09-21 16:51:12
我执行sql语句“select url,urltime from table1”,取出的记录存在m_ptrRs中(共两个字段),其中
url字段中的数据我将他存倒数组sUrl[MAX_URL]中,然后对该数组进行处理,结果存在另一个数组
sUrlTime[MAX_URL],两个数组的元素是一一对应的,请问如何将sUrlTime[MAX_URL]数组中的元素存到
m_ptrRs的urltime字段中,并将其更新到表table1中?
gwmboss@263.net

8 个解决方案

#1


请各位高人快点回复,谢谢

#2


先问一句,url和urltime是什么类型的!

#3


都是CString
数组也是,我使用多线程对sUrl数组进行处理的,可是处理完毕后似乎记录和表更新有问题
#define MAX_ADDR 50000
#define MAX_THREADS 20
CString sAddress[MAX_ADDR];
bool    bAssigned[MAX_ADDR];
bool    bFinished[MAX_ADDR];
CString sTime[MAX_ADDR];
int nSites;
int nTasks;
int nThreads;
CCriticalSection cs;
// ***************
// *             *
// *  VisitSite  *
// *             *
// ***************
// Description: Thread routine to visit sites

UINT VisitSite(LPVOID pParam)
{
CRobotInternet internet;
int nResult;
CString sHeader, sModified,sErrMsg;
int nTask;

while(nTasks > 0) // While there is work to do,从后往前来,nTasks由大变小
{
// Find a site to process
nTask = -1;
cs.Lock();
for (int t = 0; t < nSites; t++)
{
if (!bAssigned[t])
{
bAssigned[t] = true;
nTask = t;
t = nSites;
} // End if
} // End for
cs.Unlock();
/* If there are no more sites to process, 
   shut down this thread */
if (nTask == -1)
{
cs.Lock();
nThreads--;
cs.Unlock();
return 0;
} // end if
// Attempting to read a header from the site
if (internet.httpHeaderFields(sAddress[nTask],
sHeader,
nResult,
sErrMsg))
{
internet.httpGetHeaderField("last-modified",sModified);
            if(sModified=="")
{
    cs.Lock();
                sTime[nTask]="N/A";             
    cs.Unlock();
}
else
{
cs.Lock();
                sTime[nTask]=sModified;             
    cs.Unlock();
}
           
} // End if
else
{
            cs.Lock();
            sTime[nTask]=sErrMsg;             
cs.Unlock();
}
// Mark site as finished and decrement task count
cs.Lock();
bFinished[nTask] = true;
nTasks--;
cs.Unlock();
} // End while
cs.Lock();
nThreads--;
cs.Unlock();
return 0;
}
void CMTimeDlg::OnDbQueryOK() 
{
// TODO: Add your control notification handler code here
    HRESULT hr=S_OK;
hr=m_ptrRs.CreateInstance(__uuidof(Recordset));
if(FAILED(hr))
_com_issue_error(hr);
    GetDlgItemText(IDC_SQL,m_strCmdText);
hr=m_ptrRs->Open((LPCTSTR)m_strCmdText,(LPCTSTR)m_strConnectString,
adOpenKeyset,adLockOptimistic,adCmdText);
if(FAILED(hr))
_com_issue_error(hr);

if(m_ptrRs->adoEOF)
{
AfxMessageBox("没有匹配的记录!",MB_OKCANCEL);
m_ptrRs->Close();
return;
}

long nRecordCount=0;//记录数
//int nTimes=0;
while(!m_ptrRs->adoEOF)//计算记录数
{
nRecordCount++;
m_ptrRs->MoveNext();
}
m_ptrRs->MoveFirst();
    
/* if(nRecordCount%MAX_ADDR==0)//计算页数
{
nTimes=int(nRecordCount/MAX_ADDR);
}
else
{
nTimes=int(nRecordCount/MAX_ADDR)+1;
    }*/

_bstr_t bstrFieldName0=m_ptrRs->Fields->GetItem((long)0)->GetName();
    CString strFieldName=_com_util::ConvertBSTRToString(bstrFieldName0);

// for(int i=0;i<nTimes;i++)
// {
for(long i=0;i<MAX_ADDR;i++)//将sAddress[]和sTime[]全部置空
{
sAddress[i]="";
sTime[i]="";
}
    //    m_nPage=i;
        //_bstr_t bstrFieldName=m_ptrRs->Fields->GetItem((long)0)->GetName();
        //CString strFieldName=_com_util::ConvertBSTRToString(bstrFieldName);

    while(!m_ptrRs->adoEOF)
{    
 /*for(long k=0;k<MAX_ADDR;k++)
 {
     if(m_ptrRs->adoEOF)
{
break;
}
else
{*/
for(long j=0;j<nRecordCount;j++)//将记录值赋给sAddress[]数组
{
    _variant_t varFieldName;
            _variant_t varFieldValue;
    char* pName=strFieldName.GetBuffer(strFieldName.GetLength());
        varFieldName.SetString(pName);
        varFieldValue=m_ptrRs->GetCollect(varFieldName);
    varFieldValue.ChangeType(VT_BSTR);
    sAddress[j]=varFieldValue.bstrVal;
    m_ptrRs->MoveNext();

}
}

nSites=0;
nTasks=0;
while(nSites<nRecordCount)//初始化bAssigned[]和bFinished[]数组
{
bAssigned[nSites]=FALSE; 
bFinished[nSites]=FALSE;
nSites++;//都为nRecordCount大小
nTasks++;//当nTasks=0时,程序结束
}

nThreads=0;//正在运行的线程数
for(int n=0;n<MAX_THREADS;n++)//启动线程,20个
{
AfxBeginThread(VisitSite,NULL);
nThreads++;
}

    SetTimer(1,1000,NULL);
m_ptrRs->MoveFirst();
//写结果到数据库
    for(long k=0; k<nRecordCount; k++)
{
//_variant_t varRFieldName;
        _variant_t varRFieldValue;
    char* pTime=sTime[k].GetBuffer(sTime[k].GetLength());
varRFieldValue=_com_util::ConvertStringToBSTR(pTime);
m_ptrRs->PutCollect((long)1,varRFieldValue);
//m_ptrRs->Update((long)1,varRFieldValue);
m_ptrRs->MoveNext();
}
    //更新记录,更新表 
    m_ptrRs->UpdateBatch(adAffectAll); 
m_ptrRs->Close();
//SetTimer(1,1000,NULL);
}

void CMTimeDlg::OnTimer(UINT nIDEvent) 
{
// TODO: Add your message handler code here and/or call default
KillTimer(1);
if(nTasks>0||nThreads>0)
{
m_sStatus.Format("剩余URL数:%d,活动线程数:%d",nTasks,nThreads);
UpdateData(FALSE);
SetTimer(1,1000,NULL);
}
else
{
m_sStatus="完成";
GetDlgItem(IDOK)->EnableWindow(TRUE);
UpdateData(FALSE);
}
}

#4


我建议你看一下机械工业出版社的<<Visual C++6.0 数据库开发技术>>的最后一章用ADO开发数据库应用程序。
象返回的记录数可以用m_ptrRs->RecordCount这个属性来获得。
然后对应每一条记录可以用一个类来处理。
#import "c:\program files\common files\system\ado\msado15.dll"  rename_namespace("ADOCG") rename("EOF", "EndOfFile")
using namespace ADOCG;
#include <icrsint.h>



class CDataRecord:public CADORecordBinding
{
BEGIN_ADO_BINDING(CDataRecord)
ADO_VARIABLE_LENGTH_ENTRY4(1,adVarChar,re_id,sizeof(re_id),TRUE)
ADO__LENGTH_ENTRY2(2,adInteger,xx,TRUE)

END_ADO_BINDING()
public:
BYTE  re_id[21];          //对应数据库中的字段       varchar(20)
         int xx                    //对应数据库中的字段       int 
};
具体实现可以用下面的一段代码:

void GetRecord()
{
char szQuery[2048];
_bstr_t strResult;
    CoInitialize(NULL);

_ConnectionPtr m_pConnection;//先声明变量
_CommandPtr m_pCommand;
_RecordsetPtr m_rst;
_RecordsetPtr m_rstNew;
IADORecordBinding *m_piAdoRecordBinding;
CDataRecord *m_rsRecSet;
m_rsRecSet=new CDataRecord;
HRESULT hr;//开始初始化变量
long lRecordCount; 
    _bstr_t strQry;
char pcConnect[800];
try{
hr=m_pConnection.CreateInstance(__uuidof(Connection));
if(SUCCEEDED(hr))
{
strcpy(pcConnect,"provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\\test.MDB;");
_bstr_t strConnect(pcConnect);
hr=m_pConnection->Open(strConnect,
_bstr_t(L"Admin"),
_bstr_t(L""),
adModeUnknown);//连接数据库
if(FAILED(hr))
{
MessageBox(NULL,"数据库连接失败!","错误",MB_OK|MB_ICONSTOP);
return;
}
}else return;
m_rst.CreateInstance(__uuidof(Recordset));
char szQueryNew[1000];
strcpy(szQuery, "SELECT * fROM tbl_yqj");
strcpy(szQueryNew,"insert into mytest values(\"11\",16)");
strQry=(_bstr_t)szQuery;
m_rst->Open(strQry, _variant_t((IDispatch*)m_pConnection, true),
adOpenKeyset, adLockOptimistic, adCmdText);
lRecordCount = m_rst->RecordCount;
if(lRecordCount<=0)
{
m_pConnection->Close();
MessageBox(NULL,"没有相应的数据!","错误",MB_OK|MB_ICONSTOP);
return;
}
m_piAdoRecordBinding=NULL;
m_rst->QueryInterface(_uuidof(IADORecordBinding),(LPVOID *)&m_piAdoRecordBinding);
if(!m_piAdoRecordBinding) 
{
m_rst->Close();
m_pConnection->Close();
MessageBox(NULL,"没有查询到端口","错误",MB_OK|MB_ICONSTOP);
return;
}
m_piAdoRecordBinding->BindToRecordset(m_rsRecSet);
m_rst->PageSize=10;
m_rst->AbsolutePage=(PositionEnum)1;
for(int i=0;i<m_rst->PageSize;i++)
{
sprintf(szQuery,"%s",m_rsRecSet->re_id);
AfxMessageBox(szQuery);
sprintf(szQuery,"%d",m_rsRecSet->xx);
AfxMessageBox(szQuery);
m_rst->MoveNext();
if (m_rst->EndOfFile) break;
}
m_rst->Close();
}catch(_com_error &e)
{
PrintComError(e);
}

}

void PrintComError(_com_error &e)
{
   _bstr_t bstrSource(e.Source());
   _bstr_t bstrDescription(e.Description());

    // Print Com errors.
   printf("Error\n");
   printf("\tCode = %08lx\n", e.Error());
   printf("\tCode meaning = %s\n", e.ErrorMessage());
   printf("\tSource = %s\n", (LPCSTR) bstrSource);
   printf("\tDescription = %s\n", (LPCSTR) bstrDescription);
}

这样你将获得的记录数据转入你的数组中去,然后再对应的进行修改,修改完之后再用
     m_piAdoRecordBinding->Update(m_rsRecSet);进行更新,但首先要定位到该条记录然后修改m_rsRecSet的内容,再执行上面的一句。

m_piAdoRecordBinding->AddNew(m_rsRecSet);可用来增加记录,增加完后要移动一下,切记,否则加不进去的,如m_rst->MoveNext();

你还是看一下那本书吧。



#5


那个类应该是这样的。少加了一个FIXED
class CDataRecord:public CADORecordBinding
{
BEGIN_ADO_BINDING(CDataRecord)
ADO_VARIABLE_LENGTH_ENTRY4(1,adVarChar,re_id,sizeof(re_id),TRUE)
ADO_FIXED_LENGTH_ENTRY2(2,adInteger,xx,TRUE)

END_ADO_BINDING()
public:
BYTE  re_id[21];          //对应数据库中的字段      varchar(20)
        int xx                    //对应数据库中的字段      int 
};

#6


to liouyun(四海任逍遥):我想请你看看,我上面的代码,看看能否实现我的意图,或者稍加修改也可以。你的方法我觉得不太适合我的程序?

#7


难道没有其他高人了吗?
我想把数据库更新放到线程中,不只可行吗?

#8


没有人回复,结贴

#1


请各位高人快点回复,谢谢

#2


先问一句,url和urltime是什么类型的!

#3


都是CString
数组也是,我使用多线程对sUrl数组进行处理的,可是处理完毕后似乎记录和表更新有问题
#define MAX_ADDR 50000
#define MAX_THREADS 20
CString sAddress[MAX_ADDR];
bool    bAssigned[MAX_ADDR];
bool    bFinished[MAX_ADDR];
CString sTime[MAX_ADDR];
int nSites;
int nTasks;
int nThreads;
CCriticalSection cs;
// ***************
// *             *
// *  VisitSite  *
// *             *
// ***************
// Description: Thread routine to visit sites

UINT VisitSite(LPVOID pParam)
{
CRobotInternet internet;
int nResult;
CString sHeader, sModified,sErrMsg;
int nTask;

while(nTasks > 0) // While there is work to do,从后往前来,nTasks由大变小
{
// Find a site to process
nTask = -1;
cs.Lock();
for (int t = 0; t < nSites; t++)
{
if (!bAssigned[t])
{
bAssigned[t] = true;
nTask = t;
t = nSites;
} // End if
} // End for
cs.Unlock();
/* If there are no more sites to process, 
   shut down this thread */
if (nTask == -1)
{
cs.Lock();
nThreads--;
cs.Unlock();
return 0;
} // end if
// Attempting to read a header from the site
if (internet.httpHeaderFields(sAddress[nTask],
sHeader,
nResult,
sErrMsg))
{
internet.httpGetHeaderField("last-modified",sModified);
            if(sModified=="")
{
    cs.Lock();
                sTime[nTask]="N/A";             
    cs.Unlock();
}
else
{
cs.Lock();
                sTime[nTask]=sModified;             
    cs.Unlock();
}
           
} // End if
else
{
            cs.Lock();
            sTime[nTask]=sErrMsg;             
cs.Unlock();
}
// Mark site as finished and decrement task count
cs.Lock();
bFinished[nTask] = true;
nTasks--;
cs.Unlock();
} // End while
cs.Lock();
nThreads--;
cs.Unlock();
return 0;
}
void CMTimeDlg::OnDbQueryOK() 
{
// TODO: Add your control notification handler code here
    HRESULT hr=S_OK;
hr=m_ptrRs.CreateInstance(__uuidof(Recordset));
if(FAILED(hr))
_com_issue_error(hr);
    GetDlgItemText(IDC_SQL,m_strCmdText);
hr=m_ptrRs->Open((LPCTSTR)m_strCmdText,(LPCTSTR)m_strConnectString,
adOpenKeyset,adLockOptimistic,adCmdText);
if(FAILED(hr))
_com_issue_error(hr);

if(m_ptrRs->adoEOF)
{
AfxMessageBox("没有匹配的记录!",MB_OKCANCEL);
m_ptrRs->Close();
return;
}

long nRecordCount=0;//记录数
//int nTimes=0;
while(!m_ptrRs->adoEOF)//计算记录数
{
nRecordCount++;
m_ptrRs->MoveNext();
}
m_ptrRs->MoveFirst();
    
/* if(nRecordCount%MAX_ADDR==0)//计算页数
{
nTimes=int(nRecordCount/MAX_ADDR);
}
else
{
nTimes=int(nRecordCount/MAX_ADDR)+1;
    }*/

_bstr_t bstrFieldName0=m_ptrRs->Fields->GetItem((long)0)->GetName();
    CString strFieldName=_com_util::ConvertBSTRToString(bstrFieldName0);

// for(int i=0;i<nTimes;i++)
// {
for(long i=0;i<MAX_ADDR;i++)//将sAddress[]和sTime[]全部置空
{
sAddress[i]="";
sTime[i]="";
}
    //    m_nPage=i;
        //_bstr_t bstrFieldName=m_ptrRs->Fields->GetItem((long)0)->GetName();
        //CString strFieldName=_com_util::ConvertBSTRToString(bstrFieldName);

    while(!m_ptrRs->adoEOF)
{    
 /*for(long k=0;k<MAX_ADDR;k++)
 {
     if(m_ptrRs->adoEOF)
{
break;
}
else
{*/
for(long j=0;j<nRecordCount;j++)//将记录值赋给sAddress[]数组
{
    _variant_t varFieldName;
            _variant_t varFieldValue;
    char* pName=strFieldName.GetBuffer(strFieldName.GetLength());
        varFieldName.SetString(pName);
        varFieldValue=m_ptrRs->GetCollect(varFieldName);
    varFieldValue.ChangeType(VT_BSTR);
    sAddress[j]=varFieldValue.bstrVal;
    m_ptrRs->MoveNext();

}
}

nSites=0;
nTasks=0;
while(nSites<nRecordCount)//初始化bAssigned[]和bFinished[]数组
{
bAssigned[nSites]=FALSE; 
bFinished[nSites]=FALSE;
nSites++;//都为nRecordCount大小
nTasks++;//当nTasks=0时,程序结束
}

nThreads=0;//正在运行的线程数
for(int n=0;n<MAX_THREADS;n++)//启动线程,20个
{
AfxBeginThread(VisitSite,NULL);
nThreads++;
}

    SetTimer(1,1000,NULL);
m_ptrRs->MoveFirst();
//写结果到数据库
    for(long k=0; k<nRecordCount; k++)
{
//_variant_t varRFieldName;
        _variant_t varRFieldValue;
    char* pTime=sTime[k].GetBuffer(sTime[k].GetLength());
varRFieldValue=_com_util::ConvertStringToBSTR(pTime);
m_ptrRs->PutCollect((long)1,varRFieldValue);
//m_ptrRs->Update((long)1,varRFieldValue);
m_ptrRs->MoveNext();
}
    //更新记录,更新表 
    m_ptrRs->UpdateBatch(adAffectAll); 
m_ptrRs->Close();
//SetTimer(1,1000,NULL);
}

void CMTimeDlg::OnTimer(UINT nIDEvent) 
{
// TODO: Add your message handler code here and/or call default
KillTimer(1);
if(nTasks>0||nThreads>0)
{
m_sStatus.Format("剩余URL数:%d,活动线程数:%d",nTasks,nThreads);
UpdateData(FALSE);
SetTimer(1,1000,NULL);
}
else
{
m_sStatus="完成";
GetDlgItem(IDOK)->EnableWindow(TRUE);
UpdateData(FALSE);
}
}

#4


我建议你看一下机械工业出版社的<<Visual C++6.0 数据库开发技术>>的最后一章用ADO开发数据库应用程序。
象返回的记录数可以用m_ptrRs->RecordCount这个属性来获得。
然后对应每一条记录可以用一个类来处理。
#import "c:\program files\common files\system\ado\msado15.dll"  rename_namespace("ADOCG") rename("EOF", "EndOfFile")
using namespace ADOCG;
#include <icrsint.h>



class CDataRecord:public CADORecordBinding
{
BEGIN_ADO_BINDING(CDataRecord)
ADO_VARIABLE_LENGTH_ENTRY4(1,adVarChar,re_id,sizeof(re_id),TRUE)
ADO__LENGTH_ENTRY2(2,adInteger,xx,TRUE)

END_ADO_BINDING()
public:
BYTE  re_id[21];          //对应数据库中的字段       varchar(20)
         int xx                    //对应数据库中的字段       int 
};
具体实现可以用下面的一段代码:

void GetRecord()
{
char szQuery[2048];
_bstr_t strResult;
    CoInitialize(NULL);

_ConnectionPtr m_pConnection;//先声明变量
_CommandPtr m_pCommand;
_RecordsetPtr m_rst;
_RecordsetPtr m_rstNew;
IADORecordBinding *m_piAdoRecordBinding;
CDataRecord *m_rsRecSet;
m_rsRecSet=new CDataRecord;
HRESULT hr;//开始初始化变量
long lRecordCount; 
    _bstr_t strQry;
char pcConnect[800];
try{
hr=m_pConnection.CreateInstance(__uuidof(Connection));
if(SUCCEEDED(hr))
{
strcpy(pcConnect,"provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\\test.MDB;");
_bstr_t strConnect(pcConnect);
hr=m_pConnection->Open(strConnect,
_bstr_t(L"Admin"),
_bstr_t(L""),
adModeUnknown);//连接数据库
if(FAILED(hr))
{
MessageBox(NULL,"数据库连接失败!","错误",MB_OK|MB_ICONSTOP);
return;
}
}else return;
m_rst.CreateInstance(__uuidof(Recordset));
char szQueryNew[1000];
strcpy(szQuery, "SELECT * fROM tbl_yqj");
strcpy(szQueryNew,"insert into mytest values(\"11\",16)");
strQry=(_bstr_t)szQuery;
m_rst->Open(strQry, _variant_t((IDispatch*)m_pConnection, true),
adOpenKeyset, adLockOptimistic, adCmdText);
lRecordCount = m_rst->RecordCount;
if(lRecordCount<=0)
{
m_pConnection->Close();
MessageBox(NULL,"没有相应的数据!","错误",MB_OK|MB_ICONSTOP);
return;
}
m_piAdoRecordBinding=NULL;
m_rst->QueryInterface(_uuidof(IADORecordBinding),(LPVOID *)&m_piAdoRecordBinding);
if(!m_piAdoRecordBinding) 
{
m_rst->Close();
m_pConnection->Close();
MessageBox(NULL,"没有查询到端口","错误",MB_OK|MB_ICONSTOP);
return;
}
m_piAdoRecordBinding->BindToRecordset(m_rsRecSet);
m_rst->PageSize=10;
m_rst->AbsolutePage=(PositionEnum)1;
for(int i=0;i<m_rst->PageSize;i++)
{
sprintf(szQuery,"%s",m_rsRecSet->re_id);
AfxMessageBox(szQuery);
sprintf(szQuery,"%d",m_rsRecSet->xx);
AfxMessageBox(szQuery);
m_rst->MoveNext();
if (m_rst->EndOfFile) break;
}
m_rst->Close();
}catch(_com_error &e)
{
PrintComError(e);
}

}

void PrintComError(_com_error &e)
{
   _bstr_t bstrSource(e.Source());
   _bstr_t bstrDescription(e.Description());

    // Print Com errors.
   printf("Error\n");
   printf("\tCode = %08lx\n", e.Error());
   printf("\tCode meaning = %s\n", e.ErrorMessage());
   printf("\tSource = %s\n", (LPCSTR) bstrSource);
   printf("\tDescription = %s\n", (LPCSTR) bstrDescription);
}

这样你将获得的记录数据转入你的数组中去,然后再对应的进行修改,修改完之后再用
     m_piAdoRecordBinding->Update(m_rsRecSet);进行更新,但首先要定位到该条记录然后修改m_rsRecSet的内容,再执行上面的一句。

m_piAdoRecordBinding->AddNew(m_rsRecSet);可用来增加记录,增加完后要移动一下,切记,否则加不进去的,如m_rst->MoveNext();

你还是看一下那本书吧。



#5


那个类应该是这样的。少加了一个FIXED
class CDataRecord:public CADORecordBinding
{
BEGIN_ADO_BINDING(CDataRecord)
ADO_VARIABLE_LENGTH_ENTRY4(1,adVarChar,re_id,sizeof(re_id),TRUE)
ADO_FIXED_LENGTH_ENTRY2(2,adInteger,xx,TRUE)

END_ADO_BINDING()
public:
BYTE  re_id[21];          //对应数据库中的字段      varchar(20)
        int xx                    //对应数据库中的字段      int 
};

#6


to liouyun(四海任逍遥):我想请你看看,我上面的代码,看看能否实现我的意图,或者稍加修改也可以。你的方法我觉得不太适合我的程序?

#7


难道没有其他高人了吗?
我想把数据库更新放到线程中,不只可行吗?

#8


没有人回复,结贴