以前用过ODBC忘了不少,准备学着开始用ADO了。
ODBC有几种访问数据库的方式。
首先要创建好数据库,然后注册数据源。注册数据源可以用API函数实现。
一个CDatabase对象对应一个数据库。一般可以设置为全局的,在程序初始化时打开,在程序结束前关闭。
CDatabase g_db;
g_db.Open(...);
接下来使用CRecordset类,有两种方式:
1.在需要访问的地方定义临时变量,CRecordset set(&g_db);
查询时:CString strSQL;
strSQL.Format(_T("select * from info_table where id = %s"),m_id);
set.Open(CRecordset::forwardonly,strSQL);
while(!set.ISEOF())
{
........
set.MoveNext();
}
执行更新,插入操作时可以:g_db.ExecuteSQL(strSQL);strSQL里是相应的SQL语句了
2.上述方法灵活但是不清晰,另一种通常的做法是针对每一个表建立一个类派生自CRecordset:
如:
//////////////////////////////////////////RstClass.h
class CRstClass : public CRecordset
{
public:
CRstClass(CDatabase* pDatabase = NULL);
DECLARE_DYNAMIC(CRstClass)
// Field/Param Data
//{{AFX_FIELD(CRstClass, CRecordset)
long m_F_ID;
CString m_F_AutoNo;
CString m_F_Teacher;
CTime m_F_Date;
long m_F_Noon;
CString m_F_Remark;
//}}AFX_FIELD
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CRstClass)
public:
virtual CString GetDefaultConnect(); // Default connection string
virtual CString GetDefaultSQL(); // Default SQL for Recordset
virtual void DoFieldExchange(CFieldExchange* pFX); // RFX support
//}}AFX_VIRTUAL
// Implementation
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
};
///////////////////////////////////////////////RstClass.cpp
CString CRstClass::GetDefaultConnect()
{
return _T("ODBC;DSN=Auto");
}
CString CRstClass::GetDefaultSQL()
{
return _T("[T_Class]");
}
void CRstClass::DoFieldExchange(CFieldExchange* pFX)
{
//{{AFX_FIELD_MAP(CRstClass)
pFX->SetFieldType(CFieldExchange::outputColumn);
RFX_Long(pFX, _T("[F_ID]"), m_F_ID);
RFX_Text(pFX, _T("[F_AutoNo]"), m_F_AutoNo);
RFX_Text(pFX, _T("[F_Teacher]"), m_F_Teacher);
RFX_Date(pFX, _T("[F_Date]"), m_F_Date);
RFX_Long(pFX, _T("[F_Noon]"), m_F_Noon);
RFX_Text(pFX, _T("[F_Remark]"), m_F_Remark);
//}}AFX_FIELD_MAP
}
当用向导生成CRecordset的派生类是会有一个选择框让你选择一个表,然后会将表中的字段与类的成员变量进行绑定。
这样以后一切都变得清晰了:
当要操作一个表如:info_table
对应的CRecordset派生类为:CSetInfo_table;
针对没条记录再见一个类:Cinfo_tableObj;
首先定义一个对象CSetInfo_table set(&g_db);//也可以在CSetinfo_table的构造函数中指定m_pDatabase为 &g_db,这里就不需要参数了,如果都没有指定,则调用GetDefaultConnect()函数获取,也就是说当我们指定了,GetDefaultConnect()函数将不会被调用
查询:其实有两种方式,第一种同上,第二种是给m_strFilter成员变量赋值然后set.Open()就可以了
然后while(!set.IsEOF())
{
Cinfo_tableObj *pObj = new Cinfo_tableObj();
pObj->FillBySet(set);
m_array.add(pObj);
}
添加新记录
set.m_strFilter.Format("F_TableName='%s'",sTableName);
set.Open();
set.AddNew();
pObj->FillToSet(set);
set.Update();
更新新纪录
set.m_strFilter.Format(_T("...."));
set.Open();
set.Edit();
set.FillToSet(set);
set.Update();
用户DSN只在本机上用,系统DSN可以在整个网络上用
可以利用已有的数据源如 MS Access Database;
数据库连接的时候指定一个数据库就行了,如:
strCon.Format("DSN=MS Access Database;DBQ=%s;DefaultDir=%s;DriverId=281;FIL=MS Access;MaxBufferSize=2048;PageTimeout=5;UID=admin;",
m_sDBN,
m_sAppPath);
m_db.OpenEx(strCon,CDatabase::noOdbcDialog);
暂且到这里