ODBC ~

 

ODBC第一次接触。

先写一下收获:)  再写一下憋闷的接触过程.

动态的获得数据

1           不加载游标库 也就是可以直接创建一个CDatabase m_db; m_db.OpenEx("conn str...",这个参数不要CDatabase::useCursorLib);因为加载游标库后,必须进行数据绑定(我原来的CMyRecordSet就是自己写的方法根据m_rgODBCFieldInfos中记录的类型动态创建变量进行动态绑定 ````,还高兴了半天)

2           可以直接用CRecordSet 来执行 SQL 语句(不过是通过Open函数,把已经打开的数据库和待执行的SQL作为参数即可)---不用再为每个表对应一个CRecordSet派生类拉 ~

3           直接调用 MoveNext GetFieldValue (如果是设置了多行读取,默认情况下将取得第一行的数据,需要调用 SetRowsetCursorPosition来指明哪行)

使用多行同时读取

1           设置数据集CRecordset 选项加上 CRecordset::useMultiRowFetch

2           设置同时读取的行数 SetRowsetSize( DWORD dwNewRowsetSize ); 默认读取25行。
 
通过GetRowsetSize()可得到读取的行数

3           调用GetFieldValue前,先调用SetRowsetCursorPosition 设置获取哪行

4           还有值得注意的是,使用了多行读取,将不能使用Double Buffer ,类似MFC文档中使用的CMirrorFile 对原始文件的保护吧 ,具体没咋看。以后再说拉……

看了好几本的书都没看到这些,还是MSDN, 憋闷. 浪费俺时间的书

OK 上面是刚看MSDN.

 

接下来说说我原来对数据绑定的处理。一开始看了几本书,都是直接使用向导生成一个和表对应的类(派生于 CRecordset),并且表中的数据域分别在类中有对应的变量。在数据交换函数中,硬编码进行地址映射。(当然了那时候没用过ODBC,图快直接看书,看例子,没看MSDN)。 就想咋的这么死呢。于是跟踪了一下CRecordset Open代码。

//-@ CRecordset::Open中部分代码

//-@ 创建SQL语句,并解析后执行或者直接执行

BuildSQL(lpszSQL);

PrepareAndExecute();

 

//-@ 获得并保存各字段的相关信息,(在这里便可以知道result集各个域的信息)

AllocAndCacheFieldInfo();

//-@ 如果是多行读取时分配rowset(否则只标记行数为1))

AllocRowset();

 

//-@ 延迟绑定数据时,在这里进行分配字段状态数组空间

if (bUnbound && (m_nFields > 0 || m_nParams > 0))

    AllocStatusArrays();

 

//-@ 给派生类定制一些操作(在数据绑定之前)

//-@ 我重载了这个函数,并根据上面记录的 result集中各个域的信息

//-@(类型,域名等)动态创建变量。然后在数据交换(绑定)函数中使用

//-@ 我自己的函数

PreBindFields();

 

//-@ 获得第一行数据(第一次调用时,将进行变量地址同结果集各域的绑定)

//-@ 如果没有进行绑定那么这里将会出错,既然是在这里才绑定那就好办了

//-@ 我就来个动态绑定(不是硬编码),在这之前,又刚好有一个 PreBindFields

//-@ 给我定制,嘿嘿(不用重写一个Open copy paste了)

MoveNext();

 

 

//-@ CMyRecordset 内部辅助类 DataExchangeHelper

DataExchangeHelper m_dataExchHelp;

//-@ 重写的PreBindFields

//-@ 该函数根据结果集域信息动态创建变量并保存到CPtrArray

m_dataExchHelp.AllocData(this->m_rgODBCFieldInfos,

this->GetODBCFieldCount());

//-@ 重写的数据交换函数

void CMyRecordSet::DoFieldExchange(CFieldExchange* pFX)

{

    pFX->SetFieldType(CFieldExchange::outputColumn);

 

    //-@  CFieldExchange::Name用来生成SQL语句

    if(pFX->m_nOperation != CFieldExchange::Name)

    {

        m_dataExchHelp.DoDataExchange(pFX);

    }

}

//-@ 实际完成数据交换函数(当然数据库的字段类型只是根据MS Access分析

//-@ 后简易的实现了一下,测试不多,可以肯定的是只能偶尔玩玩时候用) ~

void  CMyRecordSet::DataExchangeHelper::DoDataExchange(CFieldExchange* pDX)

{

    for(int i=0; i<m_typeList.size(); i++)

    {

    this->DoDataExchange(pDX,m_typeList[i],m_pDataList[i]);

    }

}

//-@ 根据参数进行调用

void  CMyRecordSet::DataExchangeHelper::DoDataExchange(CFieldExchange* pDX, int type, void* pData)

{

    ASSERT(pData);

 

    switch(type)

    {

    case SQL_LONGVARCHAR:

    case SQL_CHAR:

    case SQL_VARCHAR:

        RFX_Text(pDX,_T(""),*(CString*)pData);

        break;

    case SQL_C_LONG:

        RFX_Long(pDX,_T(""),*(long*)pData);

        break;

    case SQL_C_SHORT:

        RFX_Int(pDX,_T(""),*(int*)pData);

        break;

    case SQL_C_FLOAT:

        RFX_Single(pDX,_T(""),*(float*)pData);

        break;

    case SQL_C_DOUBLE:

        RFX_Double(pDX,_T(""),*(double*)pData);

        break;

    case SQL_C_TIME:

    case SQL_C_TYPE_TIME:

        RFX_Date(pDX,_T(""),*(CTime*)pData);

        break;

    case SQL_C_TIMESTAMP:

    case SQL_C_TYPE_TIMESTAMP:

        RFX_Date(pDX,_T(""),*(TIMESTAMP_STRUCT*)pData);

        break;

    case SQL_C_BINARY:

        RFX_Binary(pDX,_T(""),*(CByteArray*)pData);

        break;

    case SQL_C_BIT:

        RFX_Byte(pDX,_T(""),*(BYTE*)pData);

        break;

    }

}

 

下面是内部类的声明

 

class DataExchangeHelper

    {

    public:

        DataExchangeHelper();

        ~DataExchangeHelper();

 

        //-@ 调用数据交换

        void    DoDataExchange(CFieldExchange* pDX);

       

        //-@ 根据参数进行调用

        void    DoDataExchange( CFieldExchange* pDX,

                                int type,

                                void* pData);

 

        //-@ 创建变量

        void    AllocData(  CODBCFieldInfo *pFieldInfo,

                            int count);

 

        //-@ 获得变量

        int     GetFieldsCount()const;

        void*   GetData(int idx);

        void*   GetData(const CString& name,

                        CODBCFieldInfo *pFieldInfo,

                        int count);

        CString GetDataString(int idx);

        CString GetDataString(  const CString& name,

                                CODBCFieldInfo *pFieldInfo,

                                int count);

 

        //-@ 清空数据链表

        bool    ClearDataList();

 

    protected:

        void    FieldToString(  int idx,

                                CString& outStr);

 

        //-@ 数据交换时按照顺序排列的(函数类型和绑定的数据指针)

        vector<int  >   m_typeList;

        CPtrArray       m_pDataList;

    }m_dataExchHelp;

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值