1、关于SQLServer与VC+连接的问题概述在SQL Server2005中创建数据库student,该数据库中有学生表s用来存放学生信息。s表的结构如下:属性名类型是否为主键允许空备注snochar(8)是学号snamevarchar(10)否姓名ageint否年龄deptchar(4)否所在系号commentvarchar(8)否评语基于ADO方式的实验步骤此例中所用数据库与上例中相同;此例中无需创建数据源。(1)创建VC应用程序打开VC+6.0,新建工程。选择MFC AppWizard(exe),工程名为exec2,存放在D盘实验文件夹里。点击“确定”,在弹出的窗口中选择“基本对话框”,
2、以后的步骤没有需要修改的地方,可以直接点击“完成。”这样一个基于基本对话框的工程就创建好了。(2)界面设计在工作区左边的树型结构中,选择ResourceView,展开Dialog节点,双击IDD_EXEC2_DIALOG,打开该对话框。在这里添加所需控件。如图17所示。图17为编辑框和列表框添加变量。在界面右键单击,选择“建立类向导”,弹出如图18所示窗口。图18本例中需要为编辑框IDC_AGE, IDC_COMMENT, IDC_DEPT, IDC_NAME, IDC_SNO,列表框IDC_LIST添加变量。以IDC_AGE为例,点击“ADD Variable”弹出如图19所示窗口。图19这
3、里变量名为m_age,类型可从下拉框里选。添加变量完成之后类向导如图20所示。图20为按钮添加函数,双击按钮可为其添加函数,在exec2Dig.cpp文件里。(3)与ADO相关的代码设计引入ADO库文件,使用ADO前必须在工程的StdAfx.h头文件里用直接引入符号#import引入ADO库文件,以使编译器能正确编译。代码如下所示:/加入ADO支持库#import C:Program FilesCommon FilesSystemadomsado15.dll no_namespace rename(EOF,rsEOF)/namespace是命名空间,这里不需要命名空间,主要是为了访问方便,在程
4、序中可以直接访问ADO提供的Connection、Command和Recordset这三个COM接口定义ADO连接、命令、记录集变量指针,在exec2Dlg.h文件的class CExec2Dlg : public CDialog方法中添加如下代码:/ 定义ADO连接、命令、记录集变量指针_ConnectionPtr m_pConnection;_CommandPtr m_pCommand;_RecordsetPtr m_pRecordset;/ 该指针为整个应用程序共享,所以放在public下面。初始化OLE/COM库环境。必须注意的是,ADO库是一组COM动态库,这意味应用程序在调用ADO
5、前,必须初始化OLE/COM库环境。在MFC应用程序里,一个比较好的方法是在应用程序主类的OnInitDialog()成员函数里初始化OLE/COM库环境。在本例中,在exec2.cpp文件的BOOL CExec2Dlg:OnInitDialog()成员函数里添加如下代码:/初始化COM,创建ADO连接等操作AfxOleInit();m_pConnection.CreateInstance(_uuidof(Connection);/在ADO操作中建议语句中要常用try.catch()来捕获错误信息,/因为它有时会经常出现一些想不到的错误try/打开本地Sql Server库studentm_p
6、Connection-Open(driver=SQL Server;Server=XP-201203132217SQLSERVER2005;Database=Student;UID=sa;PWD=yuzhongchun,adModeUnknown);/Server后是服务器的计算机名,注意XP-201203132217SQLSERVER2005是双斜线啊,写错了就会返回 MicrosoftODBC SQL Server DriverDBNETLIBSQL Server 不存在或访问被拒绝/Database后是数据库名/ UID=;PWD=写入相应的用户名和密码,这里使用的是SQL server
7、验证catch(_com_error e)AfxMessageBox(数据库连接失败!);return FALSE;在exec2Dlg.cpp文件中添加代码。在#endif下面添加如下代码:extern CExec2App theApp; / 在此引用应用类中的theApp来获取库连接指针在BOOL CExec2Dlg:OnInitDialog()函数中添加如下代码:/ TODO: Add extra initialization here/使用ADO创建数据库记录集m_pRecordset.CreateInstance(_uuidof(Recordset);/ 在ADO操作中建议语句中要常用
8、try.catch()来捕获错误信息,/ 因为它有时会经常出现一些想不到的错误trym_pRecordset-Open(SELECT * FROM s, / 查询s表中所有字段m_pConnection.GetInterfacePtr(), / 获取库接库的IDispatch指针adOpenDynamic,adLockOptimistic,adCmdText);catch(_com_error *e)AfxMessageBox(e-ErrorMessage();至此,与ADO相关的代码都已添加完了。下面在exec2Dlg.cpp文件中添加应用代码。(4)与功能相关的代码设计在界面上用到列表框,
9、当鼠标点击列表框的某一行时,其中的数据能够在编辑框中显示出来,这要用到列表框的一个函数。添加此函数的方法如下:摁住Ctrl和w键,进入类向导,如图21所示。图21选择IDC_LIST,在右边的Messages下面选择LBN_SELCHANGE,然后点击“Add Function”按钮,最后点击“确定”按钮,即为列表框添加了此函数。具体代码如下:/名称:OnSelchangeList/功能:当每次选择新的记录时,都会移动指针到新的记录位置并将值显示出来void CExec2Dlg:OnSelchangeList()int curSel = m_list.GetCurSel();_variant_
10、t var,varIndex;if(curSel MoveFirst();m_pRecordset-Move(long(curSel);var = m_pRecordset-GetCollect(sname);if(var.vt != VT_NULL)m_sname = (LPCSTR)_bstr_t(var);var = m_pRecordset-GetCollect(age);if(var.vt != VT_NULL)m_age=(LPCSTR)_bstr_t(var);var = m_pRecordset-GetCollect(sno);if(var.vt != VT_NULL)m_sn
11、o = (LPCSTR)_bstr_t(var);var = m_pRecordset-GetCollect(dept);if(var.vt != VT_NULL)m_dept = (LPCSTR)_bstr_t(var);var = m_pRecordset-GetCollect(comment);if(var.vt != VT_NULL)m_comment = (LPCSTR)_bstr_t(var);UpdateData(false);catch(_com_error *e)AfxMessageBox(e-ErrorMessage();将数据库中的数据显示在列表框中,添加函数ListDa
12、ta()。添加的方法是,在工作区左边的树型结构中,选择ClassView,右键单击CExec2Dlg,在弹出的菜单中选择Add Member Function,出现如图22所示的窗口,类型为void,函数描述为ListData()。图22此函数的具体代码如下:/名称:ListData/功能:将数据库中的数据显示在列表框中void CExec2Dlg:ListData()_variant_t var;CString strname,strage,strsno,strdept,strcom;/清空列表框m_list.ResetContent();strname=strage=strsno=strd
13、ept=strcom=;/在ADO操作中建议语句中要常用try.catch()来捕获错误信息,/因为它有时会经常出现一些想不到的错误。tryif(!m_pRecordset-BOF)m_pRecordset-MoveFirst();elseAfxMessageBox(表内数据为空);return;/ 读入库中各字段并加入列表框中while(!m_pRecordset-adoEOF)var = m_pRecordset-GetCollect(sno);if(var.vt != VT_NULL)strsno = (LPCSTR)_bstr_t(var);var = m_pRecordset-Get
14、Collect(sname);if(var.vt != VT_NULL)strname = (LPCSTR)_bstr_t(var);var = m_pRecordset-GetCollect(age);if(var.vt != VT_NULL)strage = (LPCSTR)_bstr_t(var);var = m_pRecordset-GetCollect(dept);if(var.vt != VT_NULL)strdept = (LPCSTR)_bstr_t(var);var = m_pRecordset-GetCollect(comment);if(var.vt != VT_NULL
15、)strcom = (LPCSTR)_bstr_t(var);m_list.AddString( strsno + - +strname + - +strage+ - + strdept+ - + strcom);m_pRecordset-MoveNext();/ 默认列表指向第一项,同时移动记录指针并显示m_list.SetCurSel(0);OnSelchangeList();catch(_com_error *e)AfxMessageBox(e-ErrorMessage();插入按钮对应的函数代码如下:/名称:OnWritedata/功能:将编辑框中输入的学生信息插入到s表中void C
16、Exec2Dlg:OnWritedata()UpdateData();if(m_sname = | m_sno = )AfxMessageBox(学号和姓名信息不能为空!);return;/在ADO操作中建议语句中要常用try.catch()来捕获错误信息,/因为它有时会经常出现一些想不到的错误。try/ 写入各字段值m_pRecordset-AddNew();m_pRecordset-PutCollect(sno, _variant_t(m_sno);m_pRecordset-PutCollect(sname, _variant_t(m_sname);m_pRecordset-PutColl
17、ect(age, atol(m_age);m_pRecordset-PutCollect(dept, _variant_t(m_dept);m_pRecordset-PutCollect(comment, _variant_t(m_comment);m_pRecordset-Update();AfxMessageBox(插入成功!);/ 更新显示其库内容int nCurSel = m_list.GetCurSel();ListData();m_list.SetCurSel(nCurSel);/ 移动记录指针到新的位置OnSelchangeList();catch(_com_error *e)A
18、fxMessageBox(e-ErrorMessage();修改按钮对应的函数代码如下:/名称:OnModify/功能:修改学生信息void CExec2Dlg:OnModify()UpdateData(); / 更新对话框数据if(m_list.GetCount() = 0)AfxMessageBox(表中记录数为空!);return;else if(m_list.GetCurSel() m_list.GetCount()m_list.SetCurSel(0);/ 修改当前记录的字段值trym_pRecordset-PutCollect(sno, _variant_t(m_sno);m_pR
19、ecordset-PutCollect(sname, _variant_t(m_sname);m_pRecordset-PutCollect(age, atol(m_age);m_pRecordset-PutCollect(dept, _variant_t(m_dept);m_pRecordset-PutCollect(comment, _variant_t(m_comment);m_pRecordset-Update();/ 重新读入库记录更新显示int nCurSel = m_list.GetCurSel();ListData();m_list.SetCurSel(nCurSel);/ 移
20、动记录指针到新的位置OnSelchangeList();catch(_com_error *e)AfxMessageBox(e-ErrorMessage();删除按钮对应的函数代码如下:/名称:OnDelete/功能:删除选中的学生信息void CExec2Dlg:OnDelete()if(m_list.GetCount() = 0)return;else if(m_list.GetCurSel() m_list.GetCount()m_list.SetCurSel(0);try/ 删除当前行记录m_pRecordset-Delete(adAffectCurrent);m_pRecordset
21、-Update();/ 删除列表中当前值int nCurSel = m_list.GetCurSel();m_list.DeleteString(nCurSel);if(nCurSel = 0 & (m_list.GetCount() != 0)m_list.SetCurSel(nCurSel);else if(m_list.GetCount() != 0)m_list.SetCurSel(nCurSel-1);/ 移动记录指针到新的位置OnSelchangeList();catch(_com_error *e)AfxMessageBox(e-ErrorMessage();查询按钮对应的函数代
22、码如下:/名称:OnQuery() /功能:按照学号和姓名查询学生信息,如果只输入学号则只按照学号查询/只输入姓名则只按照姓名查询,两者都没有输入则查询所有学生信息void CExec2Dlg:OnQuery()UpdateData(TRUE);/构造Sql语句/为简单考虑,这里只把学号和姓名作为查询条件CString strSql;if(m_sname != & m_sno != )strSql.Format(SELECT * FROM s WHERE sname = %s AND sno = %s,m_sname,m_sno);else if(m_sname != & m_sno = )s
23、trSql.Format(SELECT * FROM s WHERE sname = %s,m_sname);else if(m_sname = & m_sno != )strSql.Format(SELECT * FROM s WHERE sno = %s,m_sno);elsestrSql = SELECT * FROM s;try/先关闭已经打开的记录集对象m_pRecordset-Close();/根据新的Sql查询语句,重新打开记录集对象m_pRecordset-Open(strSql.AllocSysString(),theApp.m_pConnection.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText);catch(_com_error *e)AfxMessageBox(e-ErrorMessage();/将查询后得到的新记录集显示出来ListData();刷新按钮对应的函数代码如下:/名称:OnRefresh/功能:刷新编辑框和列表框void CExec2Dlg:OnRefresh()m_sno=;m_sname=;m_age=;m_dept=;m_comment=;m_list.ResetContent();UpdateData(false);(5)运行结果