zoukankan      html  css  js  c++  java
  • 简单的数据库应用开发(续)

    简单的数据库应用开发(续)

    三、编写工程代码

    10. 编写CMemberSystemView类的处理函数
    CMemberSystemView类的处理函数在MemberSystemView.h文件里有如下的声明:
        private:
           BOOL OpenCurRecordset(CString strTableName);
           BOOL RefreshColumn(ULONG *pulColCount);
           BOOL RefreshData(ULONG ulColCount);
           BOOL GetInfoArray(CString strTableName, CUIntArray &uaID,CStringArray &saArray);
           BOOL InsertRow(CString strTableName, CStringArray &saValues);
           BOOL DeleteRow(CString strTableName, CString strColName,CString strValue);
           CString VariantToCtring(VARIANT var);
           BOOL ConstructVar(CString strValue, int type, VARIANT *var);
        下面分别介绍这些函数的功能和实现过程。
        (1) 函数OpenCurRecordset
        函数OpenCurRecordset用于将特定的表打开,结果集存放在_RecordsetPtr对象里,参数strTableName表示表的名称。
        函数在打开结果集的时候使用的是m_recordset对象的Open方法,参数表明采用了adOpenDynamic、adLockOptimistic和adCmdText模式。
        OpenCurRecordset函数的实现代码如下:

        //OpenCurRecordset:特定表的打开,结果集存放在_RecordsetPtr所指的对象里
        //参数(Sql):查询语句
        //返回值:Bool型,用来表示打开成功与否
        BOOL CMemberSystemView::OpenCurRecordset(CString strTableName)
        {
           // 有效性检验
           if(!m_fConnected)
              return FALSE;
           if(strTableName.IsEmpty())
              return FALSE;
           HRESULT hr;
           // 构造查询语句(OpenCurRecordset函数也可以直接以sql语句为参数,以支持复杂查询)
           CString strQuery;
           strQuery.Format("select * from %s", strTableName);

           //_bstr_t query = Sql;   //用户使用的SQL语句(CString参数)

           _bstr_t query = strQuery;
           _bstr_t source =  m_strSource;
           try{
               //不能打开已打开的记录集,否则报“Unknown Error 0x800A0E79”错误
               if(m_recordset->State == adStateOpen)
                   m_recordset->Close();//adStateClosed

               //或者使用 if (m_recordset->State )   m_recordset->Close();
               hr = m_recordset->Open(query, source, adOpenDynamic,adLockOptimistic, adCmdText);
           }
           catch (_com_error &e){
                CString errormessage;
                errormessage.Format("打开记录集失败!\r\n错误信息:%s",e.ErrorMessage());
                AfxMessageBox(errormessage);//或MessageBox,显示错误信息,测试错误出在那个函数中
                return FALSE;
           }
           return (SUCCEEDED(hr));
        }
        (2) 函数RefreshColumn
        RefreshColumn函数通过m_recordset对象的get_Fields方法取得对象的列集,从该列集里得到结果集的列信息,并插入到界面中列表视图的列里。
        RefreshColumn函数的代码如下:    
        BOOL CMemberSystemView::RefreshColumn(ULONG *pulColCount)
        {
           // 有效性检验
           if(!m_fConnected)
              return FALSE;
           HRESULT hr;
           CListCtrl &listCtrl = GetListCtrl();

           listCtrl.DeleteAllItems();//首先清空列表控件原有的内容

           //DWORD exstyle = listCtrl.GetExtendedStyle();      
           //listCtrl.SetExtendedStyle(exstyle|LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES

                     | LVS_EX_CHECKBOXES | WS_EX_STATICEDGE);
           listCtrl.ModifyStyle(0,LVS_REPORT|LVS_SHOWSELALWAYS);//|LVS_SORTASCENDING使显示不正常
           listCtrl.SendMessage(LVM_SETEXTENDEDLISTVIEWSTYLE,0,LVS_EX_GRIDLINES

                     |LVS_EX_FULLROWSELECT);
           CString strColName;//保存列名
           Fields* fields = NULL;//保存记录集中的所有Field
           try{
               // 取结果集的列集
               hr = m_recordset->get_Fields(&fields);
               if (SUCCEEDED(hr))
                   hr = fields->get_Count((long *)pulColCount);//获取列数

               //-把列名在List控件中显示-//
               int index;

               for(long i=0;i<*pulColCount;i++)
               {
                   BSTR bstrColName;
                   hr = fields->Item[i]->get_Name(&bstrColName);
                   strColName = bstrColName;
                   // 插入列表视图的列
                   int nWidth = listCtrl.GetStringWidth(strColName) + 25;
                   index = listCtrl.InsertColumn(i, strColName, LVCFMT_LEFT, nWidth);
               }
               // 释放列集
               if (SUCCEEDED(hr))
                  fields->Release();
            }
            catch (_com_error &e)
            {
               MessageBox("RefreshColumn  error");//测试错误出在那个函数中

               MessageBox(e.ErrorMessage());
               return FALSE;
            }
            return (SUCCEEDED(hr));
        }
        (3) 函数RefreshData
        RefreshData函数通过调用m_recordset对象的get_adoEOF方法获知当前的结果集光标的位置是否在结果集末尾,使用 get_Item方法取得一个field对象,该对象里存放了列的数据类型和数据,我们可以通过get_Value方法取得它的值,使用 VariantToCtring函数将这个VARIANT类型的值转换成CString类型的值,VariantToCtring函数我们还要在后面介 绍,函数最后调用m_recordset对象的Close方法关闭结果集。
        RefreshData函数的实现代码如下:
        BOOL CMemberSystemView::RefreshData(ULONG ulColCount)
        {
           // 有效性检验
           if(!m_fConnected)
              return FALSE;
           if(0 == ulColCount)
              return FALSE;
           //- 变量定义 -//

           HRESULT hr;
           CListCtrl &listCtrl = GetListCtrl();//获取视图控件
           CString strValue;
           VARIANT var_value;
           VARIANT_BOOL ValEof;//是否还有记录
           int nRowCount = 0;
           Field *field = NULL;
           VARIANT varCounter;

           varCounter.vt = VT_I4;//有关VARIANT类型的说明请见MSDN的CComVariant
           varCounter.lVal = 0;
           try{
               // 取当前光标位置是否在结果集末尾
               ValEof = m_recordset->get_adoEOF(&ValEof);

               //hr = m_recordset->get_adoEOF(&ValEof);该代码作用与上相同
               while(TRUE){
                   if(ValEof) break;
                   varCounter.lVal = 0;
                   // 取一个列对象
                   m_recordset->Fields->get_Item(varCounter, &field);
                   //DataTypeEnum data_type;               
                   field->get_Value(&var_value);// 取列对象的值
                   // 转换成字符类型
                   strValue = VariantToCtring(var_value);
                   // 插入到界面列表视图里
                   listCtrl.InsertItem(nRowCount, strValue);

                   //int Colcount = (int)ulColCount;
                   //for (long i = 1; i < Colcount; i++)
                   for(int i=1;i<ulColCount;i++){
                       varCounter.lVal = i;
                       m_recordset->Fields->get_Item(varCounter, &field);
                       field->get_Value(&var_value);
                       strValue = VariantToCtring(var_value);
                       listCtrl.SetItemText(nRowCount, i, strValue);
                   }
                   nRowCount ++;
                   m_recordset->MoveNext();
                   m_recordset->get_adoEOF(&ValEof);
               }
               // 关闭结果集
               m_recordset->Close();
            }
            catch (_com_error &e){

               MessageBox("RefreshData  error");//测试错误出在那个函数中
               MessageBox(e.ErrorMessage());
               return FALSE;
            }
            return (SUCCEEDED(hr));
        }
        (4) 函数GetInfoArray
        GetInfoArray函数实现了从特定表的特定列里得到需要的信息,参数strTableName为输入的表的名称,参数uaID为输出的关键字列里的ID,参数saArray为输出列的名称。
        GetInfoArray函数的实现代码如下:
        BOOL CMemberSystemView::GetInfoArray(CString strTableName,CUIntArray &uaID,

                CStringArray &saArray)
        {
            // 有效性检验
            if(!m_fConnected)
               return FALSE;
            HRESULT hr;
            CString strQuery;
            CString strValue;
            VARIANT var_value;
            VARIANT_BOOL ValEof;
            int nRowCount = 0;
            Field *field = NULL;
            _variant_t var_t;
            _bstr_t bst_t;
            VARIANT varCounter;
            varCounter.vt = VT_I4;
            varCounter.lVal = 0;
            // 建立查询字符串
            strQuery.Format("select * from %s", strTableName);
            _bstr_t query = strQuery;
            _bstr_t source =  m_strSource;
            try{
                // 打开结果集
                hr = m_recordset->Open(query, source, adOpenDynamic,adLockOptimistic, adCmdText);
                ValEof = m_recordset->get_adoEOF(&ValEof);
                while(TRUE){
                   if(ValEof) break;
                   varCounter.lVal = 0;
                   // 读取字段内容,第1个字段为整型的行标识,如社团ID,第2个字段为社团名等字串
                   m_recordset->Fields->get_Item(varCounter, &field);
                   field->get_Value(&var_value);
                   uaID.Add(var_value.lVal);
                   varCounter.lVal = 1;
                   m_recordset->Fields->get_Item(varCounter, &field);
                   field->get_Value(&var_value);
                   var_t = var_value;
                   bst_t = var_t;
                   saArray.Add((const char *)bst_t);
                   nRowCount ++;
                   m_recordset->MoveNext();
                   m_recordset->get_adoEOF(&ValEof);
                }
                // 关闭结果集
                m_recordset->Close();
             }
             catch (_com_error &e){
                MessageBox(e.ErrorMessage());
                return FALSE;
             }
             return (SUCCEEDED(hr));
        }
        (5) 函数InsertRow
        InsertRow函数将存放在CstringArray数组里的列值添加到strTableName表里。函数首先是打开一个结果集,然后执行结果集的 插入方法AddNew,该函数只是为m_recordset对象增加了一个空的列对象,我们需要将列的值拷贝到这个列对象里,field对象的 put_Value方法可以实现列对象的复制,但是它的参数是VARIANT类型的,我们编写了ConstructVar函数将一个特定类型的值转换成 VARIANT类型。
        InsertRow函数的实现代码如下:
        BOOL CMemberSystemView::InsertRow(CString strTableName,CStringArray &saValues)
        {
            // 有效性检验
            if(!m_fConnected) return FALSE;
            if(strTableName.IsEmpty()) return FALSE;
            int nColNum = 0;
            if(0 == (nColNum = saValues.GetSize())) return FALSE;
            HRESULT hr;
            Fields* fields = NULL;
            Field* field = NULL;
            VARIANT varValue;
            VARIANT varCount;
            DataTypeEnum data_type;
            varCount.vt = VT_I4;
            // 打开结果集
            //CString tempstr;//测试用
            if(!OpenCurRecordset(strTableName)) return FALSE;
            try{
                hr = m_recordset->AddNew();
                hr = m_recordset->get_Fields(&fields);
                for(int i=0;i<nColNum;i++)
                
                    varCount.lVal = i+1;//因为第1个字段为自增字段,不需要赋值
                    hr = fields->get_Item(varCount, &field);  
                    field->get_Type(&data_type);
                    if(!ConstructVar(saValues.GetAt(i), data_type, &varValue))
                        return FALSE;
                    hr = field->put_Value(varValue);
                    //tempstr=tempstr+saValues.GetAt(i)+"  ";//测试用
                }
                m_recordset->Update();//将修改后的记录保存到数据库
                //MessageBox(tempstr);
                fields->Release();
                field->Release();
            }
            catch (_com_error &e){
               MessageBox(e.ErrorMessage());
               return FALSE;
            }
            return (SUCCEEDED(hr));

        }
        (6) 函数DeleteRow
        DeleteRow函数将特定的行从strTableName表里删除。
        函数利用输入的strIDColName列名称和strValue列值建立查询语句,从而由这个查询语句建立一个结果集,将结果集的记录删除就可以实现删除行操作。m_recordset对象的Delete方法将结果集当前行从结果集中删除。
        DeleteRow函数的实现代码如下:
        BOOL CMemberSystemView::DeleteRow(CString strTableName,CString strColName,

               CString strValue)
        {
            // 有效性检验
            if(!m_fConnected) return FALSE;
            HRESULT hr;
            CString strQuery;
            VARIANT_BOOL ValEof;
            // 构造SQL查询语句,注意字串类型的字段值要加单引号,否则报错
            strQuery.Format("select * from %s where %s='%s'",strTableName,strColName,strValue);
            _bstr_t query = strQuery;
            _bstr_t source =  m_strSource;
            try{
                hr = m_recordset->Open(query, source, adOpenDynamic,adLockOptimistic, adCmdText);
                ValEof = m_recordset->get_adoEOF(&ValEof);
                if(!ValEof) m_recordset->Delete(adAffectCurrent);//删除当前行
                m_recordset->Close();//关闭记录集的同时,记录集被重新写回数据库
            }
            catch (_com_error &e){
                //MessageBox(strQuery);
                //MessageBox("deleterow error");//测试错误出现位置
                MessageBox(e.ErrorMessage());
                return FALSE;
            }
            return (SUCCEEDED(hr));

        }
        (7) 函数VariantToCtring
        函数VariantToCtring实现了将VARIANT类型的值转换成CString类型。
        VariantToCtring函数的实现代码如下:
        CString CMemberSystemView::VariantToCtring(VARIANT var)
        {
           CString strValue;
           _variant_t var_t;
           _bstr_t bst_t;
           time_t cur_time;
           CTime time_value;
           COleCurrency var_currency;
           switch(var.vt){
               case VT_EMPTY: strValue = _T(""); break;
               case VT_UI1: strValue.Format("%d", var.bVal); break;
               case VT_I2: strValue.Format("%d", var.iVal); break;
               case VT_I4: strValue.Format("%d", var.lVal); break;
               case VT_R4: strValue.Format("%f", var.fltVal); break;
               case VT_R8: strValue.Format("%f", var.dblVal); break;
               case VT_CY:
                  var_currency = var;
                  strValue = var_currency.Format(0);
                  break;
               case VT_BSTR:
                  var_t = var;
                  bst_t = var_t;
                  strValue.Format("%s", (const char *)bst_t);
                  break;
               case VT_NULL: strValue = _T(""); break;
               case VT_DATE:
                  //cur_time = var.date;
                  //time_value = cur_time;
                  //strValue = time_value.Format("%A, %B %d, %Y");

                  //strValue = time_value.Format("%Y-%m-%d");

                  //以上语句不能取得日期字段值,固定显示“1970-1-1”
                  //time_value = CTime::GetCurrentTime();
                  //strValue = time_value.Format("%Y-%m-%d");
                   {
                     DATE dt=var.date;//在case中初始化变量的时候整体要加个大括号            
                     COleDateTime   odt    COleDateTime(dt);
                     strValue = odt.Format("%Y-%m-%d   %H:%M:%S");
                   }
                  break;
               case VT_BOOL: strValue.Format("%d", var.boolVal); break;
               default: strValue = _T(""); break;
           }
           return strValue;

        }
        (8) 函数ConstructVar
        函数ConstructVar实现了VariantToCtring函数的反向功能,将CString类型的值根据转换类型转换成为VARIANT值。
        函数ConstructVar实现代码如下:
        BOOL CMemberSystemView::ConstructVar(CString strValue, int type, VARIANT *var)
        {
           COleDateTime var_date;
           CURRENCY cy;
           cy.Hi = 0;
           switch(type){
              case adInteger:
              case adSmallInt:   
                 var->vt = VT_I4;
                 var->lVal = atoi(strValue);
                 break;
              case adCurrency://6
                 //var->vt = VT_CY;
                 //cy.Lo = atoi(strValue);
                 //cy.int64 = atoi(strValue);
                 //var->cyVal = cy;
                 //以上代码好像数据转换不正确
                 {
                    //有关数据转换的知识扩充
                    //CString   str;  
                    //COleCurrency   cur;    
                    //String   To   Currency:  
                    //_variant_t   var(str);  
                    //var.ChangeType(VT_CY);  
                    //cur    var.cyVal;  
       
                    //Currency   To   String:  
                    //_variant_t   var(cur);  
                    //var.ChengeType(VT_BSTR);  
                    //str    var.bstrVal;
                    //以下代码测试通过
                    _variant_t   _var(strValue);  
                    _var.ChangeType(VT_CY);  
                    *var    _var;
                 }
                 break;
              case adChar:
              case adVarWChar:
                 var->vt = VT_BSTR;
                 var->bstrVal = (_bstr_t)strValue;
                 break;
              case adDBTimeStamp:
                 {
                       //CString转换COleDateTime
                       //CString strDate = "2008-12-8";
                      //CString strTime = "12:50:40";
                      //COleDateTime t;
                      //t.ParseDateTime( strDate + CString(" ") + strTime );
                      var_date.ParseDateTime(strValue);
                      var->vt = VT_DATE;
                      var->date = var_date;
                 }
                 break;
              default:
                 var->vt = VT_EMPTY;
                 break;
           }
           return TRUE;

        }

     

    参考文章:

    1、COleCurrency和CString之间如何相互转换 http://topic.csdn.net/t/20030117/11/1367939.html

    2、recordset Unknown Error 0x800A0E79 http://topic.csdn.net/t/20060518/12/4760796.html

    3、有关ADO调用存储过程 http://www.roarsoft.net/html/article/article_92_485.htm

    4、判断数据库数据类型 http://hi.baidu.com/ilotus_y/blog/item/414b04b7918367f131add194.html

    5、VC 数据库编程三部教学 http://download.csdn.net/source/1254266 

  • 相关阅读:
    ubuntu11.04更改默认JDK
    10个实用的jQuery交互/通信插件和教程
    jquery 使用方法
    在没有安装 ASP.NET MVC3 的服务器上运行 MVC3
    固定 vs. 流动 vs. 弹性:哪种布局更适合你?[SM]
    提升设计品质的8种布局方案[SM]
    Ubuntu 手动安装JDK
    十个简单好用的设计技巧[SM]
    jQuery VSDoc下载地址
    Ubuntu 配置Apache+PHP+MySQL
  • 原文地址:https://www.cnblogs.com/luoshupeng/p/2146183.html
Copyright © 2011-2022 走看看