• VC编程技术点滴(七)简单的数据库应用开发


    本示例节选自《VC 数据库编程三部教学》第九章,是一个关于会员消费的简单应用,与原文相比有删节(便于理清简单数据库应用开发的思路),并修改了多处错误。 

     

    一、创建数据库表与视图

        在Sql Server企业管理器中创建数据库MyDataBase,创建登录用户并分配对数据库MyDataBase的读写权限(也可以将用户设置为数据库拥有者,但为了数据库的安全性,不可将一般用户设置为数据库管理员)。

        创建会员表Member、社团表Society、消费记录表Consumption与相关视图:

    VC编程技术点滴(七)简单的数据库应用开发

         CREATE VIEW dbo.ConsumeView
         AS
         SELECT dbo.Member.MemberID, dbo.Member.Name, dbo.Society.SocietyName, 
            dbo.Member.Sex, dbo.Member.Country, dbo.Member.Address, 
            dbo.Consumption.Amount, dbo.Consumption.ConsumeDate
         FROM dbo.Member INNER JOIN
            dbo.Consumption ON
            dbo.Member.MemberID = dbo.Consumption.MemberID INNER JOIN
            dbo.Society ON dbo.Member.SocietyID = dbo.Society.SocietyID

    二、创建工程及相关对话框资源

        创建MFC单文档List View视图应用程序应用程序,工程名为MemberSystem,保持工程创建向导的默认配置,记住在选择窗口视图类型时,选择CListView视图(参考前一章相关内容)。

        如图所示创建应用程序主菜单:

    VC编程技术点滴(七)简单的数据库应用开发

        如图所示创建会员入会对话框(IDD_MEMBER_IN):

    VC编程技术点滴(七)简单的数据库应用开发

        会员退会对话框:

    VC编程技术点滴(七)简单的数据库应用开发

        会员消费登记对话框:

    VC编程技术点滴(七)简单的数据库应用开发

        为简化程序,省略了对社团数据表的添加、编辑菜单及对话框,直接在Sql Server企业管理器中为社团表Society添加了数行示例数据。

    三、编写工程代码

    1、将ADO代码引入工程

        为了能够使用ADO,需要将ADO库引入工程。操作系统都提供了ADO代码库,它是通过DLL的形式存放的,在进行ADO编程时,首先要将这个库引入工程。

        在stdafx.h中添加引入数据库处理类库的代码:

        // stdafx.h : include file for standard system include files

        #import "f:\Program Files\Common Files\System\ado\msado15.dll" no_namespace rename

          ("EOF", "adoEOF")

    2、建立用于会员入会登记的CMemberinDlg对话框类

        以对话框IDD_MEMBER_IN作为模板建立会员入会登记的CMemberinDlg类。
        (1) 使用VC++的类视图或其类向导(View --> ClassWizard),或选择“Insert --> New Class”菜单命令,如下图所示完成CMemberinDlg类的创建:

    VC编程技术点滴(七)简单的数据库应用开发

        (2)创建与IDD_MEMBER_IN对话框中控件相关联的变量。这些变量的名称、类型以及与之关联的控件ID如下所示:

                        m_strName       CString       IDC_NAME      存放会员姓名
                        m_strCardNo     CString       IDC_CARDNO    存放会员卡号
                        m_strAge        CString       IDC_AGE       存放会员年龄
                        m_strAddress    CString       IDC_ADDRESS   存放会员地址
                        m_strCountry    CString       IDC_COUNTRY   存放会员国家

                        m_CtrlSociety   CComboBox     IDC_SOCIETY   提供社团选择
                        m_CtrlGender    CComboBox     IDC_GENDER    提供性别选择

    VC编程技术点滴(七)简单的数据库应用开发

        (3)为会员登记对话框类添加成员变量,主要是存放提供选择社团名称和ID列表的数组变量、存放选择的社团ID的UINT变量、存放性别ID的UINT成员变量:

        public:

           CStringArray m_saSocietyName;
           CUIntArray m_suSocietyID;
           UINT m_uSocietyID;

           UINT m_uGenderID;//保存性别控件所选择的值

           CString m_strSex;//保存性别控件所选择的文本

           //本程序性别字段的数据类型为字符串,所以要直接把选择的“男”或“女”字串保存到性别字段

         (4) 重载CMemberinDlg类的OnInitDialog函数。为了在对话框显示的时候将社团列表显示在列表控件里,我们需要重载初始化函数:

    VC编程技术点滴(七)简单的数据库应用开发

        在OnInitDialog函数的//TODO行后面加入如下代码:
        int i, nIdx;
        for(i=0;i<m_saSocietyName.GetSize();i++){
           nIdx = m_CtrlSociety.AddString(m_saSocietyName.GetAt(i));
           m_CtrlSociety.SetItemData(nIdx, m_suSocietyID.GetAt(i));
        }
        m_CtrlSociety.SetCurSel(0); 
        m_CtrlGender.SetCurSel(0); 

        (5) 创建CMemberinDlg类的按钮IDOK的点击响应OnOK函数。在OnOK函数的//TODO行后面加入如下代码:
        // TODO: Add extra validation here
        UpdateData();
        int nIdx;
        nIdx = m_CtrlSociety.GetCurSel();
        if(-1 != nIdx)
        {
           //char szSocietyID[256] = {0};
           UINT uSocietyID;
           if(-1 != nIdx)
           {
              uSocietyID = m_CtrlSociety.GetItemData(nIdx);
              m_uSocietyID = uSocietyID;
           }
        }
        m_uGenderID = m_CtrlGender.GetCurSel();
        //获取所选择的性别字串
        //int index=m_CtrlGender.GetCurSel();
        //CString str;
        //m_combo.GetLBText(index,str);
        m_CtrlGender.GetLBText(m_uGenderID,m_strSex);

    3. 建立用于会员退会登记的CMemberoutDlg对话框类

        建立CMemberoutDlg类的过程同建立CMemberinDlg类的过程基本相似。

        创建与IDD_MEMBER_OUT对话框中控件相关联的变量。这些变量的名称、类型以及与之关联的控件ID如下所示:

                 m_strName CString IDC_NAME 会员名称变量
                 m_strDesc CString IDC_DESC 退会描述变量

    4、建立用于会员消费登记的CExpenRegDlg对话框类
        建立CExpenRegDlg类的过程同建立CMemberinDlg类的过程基本相似。

        创建与IDD_EXPENSE_REGISTER对话框中控件相关联的变量。这些变量的名称、类型以及与之关联的控件ID如下所示:

                 m_strName      CString    IDC_NAME   存放会员姓名
                 m_strCardNo    CString    IDC_CARD   存放会员卡号
                 m_strMoney     CString    IDC_MONEY  存放会员消费金额
                 m_strDesc      CString    IDC_DESC   存放用户输入的消费项目描述

    5、为视图类CMemberSystemView添加声明ADO数据库对象的成员变量:

        public:

           _RecordsetPtr m_recordset;
           _ConnectionPtr m_connection;

           _CommandPtr m_command;

        private:
           CString m_strSource;
           BOOL m_fConnected;

        变量strSource的作用是存放用于数据库连接的连接字符串,m_fConnected是标志数据库连接成功的BOOL变量。

    6、编写CMemberSystemView类的初始化函数OnInitialUpdate

        我们需要在OnInitialUpdate函数里创建ADO的数据库连接和记录集对象,这些代码如下:

        void CMemberSystemView::OnInitialUpdate()
        {
           ......

           //-  创建数据库连接   -//
           HRESULT hr;
           //---连接语句---//
           CString source

                = "driver={SQL Server};Server=localhost;DATABASE=MyDataBase;UID=test;PWD=test";

           //_bstr_t user("admin");
           //_bstr_t pwd("");

           //---开始连接---// 
           try
           {
              ::CoInitialize(NULL);//此句必须(告诉windows以什么方式为程序创建COM对象)

              //_ConnectionPtr  m_connection;//灵巧指针(smart pointer)
              hr = m_connection.CreateInstance(__uuidof(Connection));    //生成连接对象
              if (SUCCEEDED(hr))
                 //hr = m_connection->Open(source, user, pwd, 16);

                 hr = m_connection->Open((_bstr_t)source,"","",adModeUnknown); //连接数据库
              if (SUCCEEDED(hr))
                 hr = m_recordset.CreateInstance(__uuidof(Recordset));   //生成数据集对象
              if (SUCCEEDED(hr))
                 m_fConnected = true;
              else
                 m_fConnected = FALSE;

           }
           catch(_com_error &e)
           {
              CString errormessage;
              errormessage.Format("连接数据库失败!\r\n错误信息:%s",e.ErrorMessage());
              AfxMessageBox(errormessage);
              m_fConnected = FALSE;

              return;
           }
           //if(!m_fConnected) MessageBox("ADO数据源初始化失败!");
           //else  m_strSource = (const char * )source;
           m_strSource = source;//将连接语句保存

        }

        代码对连接对象和结果集对象执行CreateInstance方法,从而创建这两个对象的实例,实例创建成功以后就可以调用对象的Open方法了。连接对 象的Open方法将应用程序连接到数据源,而结果集对象的Open方法在这里并没有调用,可以在应用程序的任何地方使用Open方法打开一个结果集。 _com_error对象是COM处理错误的对象,可以从这个对象里捕获错误信息。

    7、编写CMemberSystemView类的消息映射函数
        (1) 编写“会员>入会”菜单命令的响应函数OnMemberInput
        OnMemberInput函数首先从“社团”表里读取社团信息,准备显示在“会员入会”对话框里提供给用户选择,然后将“会员入会”对话框显示给用户并等待输入,用户输入并确认后,代码将输入信息插入到“会员”表里。
        OnMemberInput函数的实现代码如下:

        ......

        #include "MemberinDlg.h"

        ......
        void CMemberSystemView::OnMemberInput()
        {
           // TODO: Add your command handler code here
           // 有效性检验
           if(!m_fConnected) return;
           // 建立临时变量
           CUIntArray uaID;
           CStringArray saArray;
           CString strTableName;
           CMemberinDlg MemberinDlg;
           // 从“社团”表里读取社团信息
           strTableName = _T("Society");
           if(!GetInfoArray(strTableName, uaID, saArray)) return;
           MemberinDlg.m_suSocietyID.Append(uaID);
           MemberinDlg.m_saSocietyName.Append(saArray);
           uaID.RemoveAll();
           saArray.RemoveAll();
           // 显示“会员入会”对话框
           if(IDOK == MemberinDlg.DoModal())
           {
              // 获取数据
              CStringArray saValue;
              char value[256] = {0};
              CString strValue;
              //要按照数据表的字段顺序
              saValue.Add(MemberinDlg.m_strName);
              itoa(MemberinDlg.m_uSocietyID, value, 10);//10表示十进制
              saValue.Add(value);
              saValue.Add(MemberinDlg.m_strCardNo);         
              //itoa(MemberinDlg.m_uGenderID, value, 10);
              //saValue.Add(value);
              //添加所选的性别字串
              saValue.Add(MemberinDlg.m_strSex);
              saValue.Add(MemberinDlg.m_strAge);
              saValue.Add(MemberinDlg.m_strCountry);
              saValue.Add(MemberinDlg.m_strAddress);        
              CTime time = CTime::GetCurrentTime();
              strValue = time.Format("%Y-%m-%d"); 
              saValue.Add(strValue);
              // 插入数据
              InsertRow("Member", saValue);
           }

        }
        (2) 编写“会员>退会”菜单命令的响应函数OnMemberExit
        OnMemberExit函数首先将“会员退会”对话框显示给用户并等待输入,用户输入并确认后,函数将“会员”表里的该会员删除。
        OnMemberExit函数的实现代码如下:

        ......

        #include "MemberoutDlg.h"

        ......
        void CMemberSystemView::OnMemberExit()
        {
            // TODO: Add your command handler code here
            CMemberoutDlg MemberoutDlg;
            if(IDOK == MemberoutDlg.DoModal())

            {
               // 执行删除
               CString strValue = MemberoutDlg.m_strName;
               CString strTableName(_T("Member"));
               if(!DeleteRow(strTableName, _T("Name"), strValue))
                  return;
            }
        }

        (3) 编写“会员>查询”菜单命令的响应函数OnMemberQuery
        OnMemberQuery函数先将当前操作表名设置为"v_会员",并打开这个表,然后从表里读取列 信息以刷新列表视图里的列标题。函数RefreshColumn在后面我们再介绍,它的功能就是从表里读取列信息以刷新列表视图里的列标题;接下来函数调 用RefreshData函数进行列表视图的数据刷新。
        OnMemberQuery函数的实现代码如下:
        void CMemberSystemView::OnMemberQuery()
        {
            // TODO: Add your command handler code here
            CString m_strCurTableName = _T("Member");
            // 清除列表视图的显示内容
            EraseList();
            ULONG ulColCount=0;
            // 打开数据库中的表
            if(!OpenCurRecordset(m_strCurTableName))
               return;
            // 刷新视图的列标题
            if(!RefreshColumn(&ulColCount))
               return;
            if(0==ulColCount)
               return;
            // 刷新视图的数据显示
            if(!RefreshData(ulColCount))
               return;

        }

        (4) 编写“消费>登记”菜单命令的响应函数OnExpenseRegister
        OnExpenseRegister函数先从“社团” 表里获得社团信息,以便在“消费登记”对话框里给用户提示,然后显示“消费登记”对话框,用户输入并确认后,将输入的消费信息插入到“消费”表里。
        OnExpenseRegister函数的实现代码如下:

        ......

        #include "ExpenRegDlg.h"

        ......
        void CMemberSystemView:: OnExpenseRegister ()
        {
           // TODO: Add your command handler code here
           CString strTableName;
           CExpenRegDlg ExpenRegDlg;
           // 显示“消费登记”对话框
           if(IDOK == ExpenRegDlg.DoModal())
           {
              // 插入数据(按照数据表的字段顺序)
              CStringArray saValue;
              char value[256] = {0};
              CString strValue;
              saValue.Add(ExpenRegDlg.m_strName);
              saValue.Add(ExpenRegDlg.m_strMoney);
              CTime time = CTime::GetCurrentTime();
              strValue = time.Format("%Y-%m-%d"); 
              saValue.Add(strValue);
              saValue.Add(ExpenRegDlg.m_strDesc);
             
              InsertRow("Consumption", saValue);
           }

        }
        (8) 编写“消费>统计”菜单命令的响应函数OnExpenseStatics
        OnExpenseStatics函数从“消费”视图里读取消费信息,并显示在视图界面上。函数代码如下:
        void CMemberSystemView::OnExpenseStatics()
        {
           // TODO: Add your command handler code here
           CString m_strCurTableName = _T("ConsumeView");
           EraseList();
           ULONG ulColCount=0;
           if(!OpenCurRecordset(m_strCurTableName))
              return;
           if(!RefreshColumn(&ulColCount))
              return;
           if(0==ulColCount)
              return;
           if(!RefreshData(ulColCount))
              return;

        }(待续)

     

       有关GetInfoArray、OpenCurRecordset、RefreshColumn、RefreshData、InsertRow、DeleteRow等函数内容请参考后续章节

  • 相关阅读:
    C#线程使用学习
    C# 线程
    C# Lambda表达式与Linq
    C#聚合运算方法
    责任链模式
    代理模式
    享元模式
    门面模式(外观模式)
    桥梁模式
    设计模式-创建型、结构型、行为型之间的区别
  • 原文地址:https://www.cnblogs.com/luoshupeng/p/2146179.html
Copyright © 2020-2023  润新知