zoukankan      html  css  js  c++  java
  • 多结果集IMultipleResult接口

    在某些任务中,需要执行多条sql语句,这样一次会返回多个结果集,在应用程序就需要处理多个结果集,在OLEDB中支持多结果集的接口是IMultipleResult。

    查询数据源是否支持多结果集

    并不是所有数据源都支持多结果集,可以通过查询数据源对象的DBPROPSET_DATASOURCEINFO属性集中的DBPROP_MULTIPLERESULTS属性来确定,该值是一个按位设置的4字节的联合值。它可取的值有下面几个:

    • DBPROPVAL_MR_SUPPORITED:支持多结果集
    • DBPROPVAL_MR_SONCURRENT:支持多结果集,并支持同时打开多个返回的结果集(如果它不支持同时打开多个结果集的话,在打开下一个结果集之前需要关闭已经打开的结果集)
    • DBPROPVAL_MR_NOTSUPPORTED: 不支持多结果集
      这个属性可以通过接口IDBProperties接口的GetProperties方法来获取,该函数的原型如下:
    HRESULT GetProperties (
       ULONG               cPropertyIDSets,
       const DBPROPIDSET   rgPropertyIDSets[],
       ULONG              *pcPropertySets,
       DBPROPSET         **prgPropertySets);
    

    它的用法与之前的SetProperties十分类似
    第一个参数是我们传入DBPROPIDSET数组元素的个数,第二个参数是一个DBPROPIDSET结构的参数,该结构的原型如下:

    typedef struct tagDBPROPIDSET {
       DBPROPID *   rgPropertyIDs;
       ULONG        cPropertyIDs;
       GUID         guidPropertySet;
    } DBPROPIDSET;
    

    该结构与之前遇到的DBPROPSET类似,第一个参数是一个DBPROPID结构的数组的首地址,该值是一个属性值,表示我们希望查询哪个属性的情况,第二个参数表示我们总共查询多少个属性的值,第3个参数表示这些属性都属于哪个属性集。
    接口方法的第三个参数返回当前我们总共查询到几个属性集的内容。
    第四个参数返回具体查到的属性值。

    多结果集接口的使用

    多结果集对象的定义如下:

    CoType TMultipleResults {
       [mandatory]   interface IMultipleResults;
       [optional]    interface ISupportErrorInfo;
    }
    

    一般在程序中,使用多结果集有如下步骤

    1. 查询数据源是否支持多结果集,如果不支持则要考虑其他的实现方案
    2. 如果它支持多结果集,在调用ICommandText接口的Execute方法执行SQL语句时,让其返回一个IMultipleRowset接口。
    3. 循环调用接口的GetResult方法获取结果集对象。
    4. 使用结果集对象

    最后是一个完整的例子:

    //判断是否支持多结果集
    BOOL SupportMultipleRowsets(IOpenRowset *pIOpenRowset)
    {
        COM_DECLARE_BUFFER();
        COM_DECLARE_INTERFACE(IDBInitialize);
        COM_DECLARE_INTERFACE(IDBProperties);
        COM_DECLARE_INTERFACE(IGetDataSource);
    
        BOOL bRet = FALSE;
    
        //定义相关结构用于获取关于多结果集的信息
        DBPROPID dbPropId[2] = {0};
        DBPROPIDSET dbPropIDSet[1] = {0};
        
        dbPropId[0] = DBPROP_MULTIPLERESULTS;
        dbPropIDSet[0].cPropertyIDs = 1;
        dbPropIDSet[0].guidPropertySet = DBPROPSET_DATASOURCEINFO;
        dbPropIDSet[0].rgPropertyIDs = dbPropId;
    
        //定义相关结构用于接受返回的属性信息
        ULONG uPropsets = 0;
        DBPROPSET *pDBPropset = NULL;
        //获取数据源对象
        HRESULT hRes = pIOpenRowset->QueryInterface(IID_IGetDataSource, (void**)&pIGetDataSource);
        COM_SUCCESS(hRes, _T("查询接口IGetDataSource失败,错误码为:%08x
    "), hRes);
        hRes = pIGetDataSource->GetDataSource(IID_IDBInitialize, (IUnknown **)&pIDBInitialize);
        COM_SUCCESS(hRes, _T("获取数据源对象失败,错误码为:%08x
    "), hRes);
    
        //获取对应属性
        hRes = pIDBInitialize->QueryInterface(IID_IDBProperties, (void**)&pIDBProperties);
        COM_SUCCESS(hRes, _T("查询IDBProperties接口失败,错误码为:%08x
    "), hRes);
        hRes = pIDBProperties->GetProperties(1, dbPropIDSet, &uPropsets, &pDBPropset);
        COM_SUCCESS(hRes, _T("获取属性信息失败,错误码:%08x
    "), hRes);
    
        //判断是否支持多结果集
        if (pDBPropset[0].rgProperties[0].vValue.vt == VT_I4)
        {
            if (pDBPropset[0].rgProperties[0].vValue.intVal & DBPROPVAL_MR_CONCURRENT)
            {
                COM_PRINT(_T("支持多结果集
    "));
            }else if (pDBPropset[0].rgProperties[0].vValue.intVal & DBPROPVAL_MR_SUPPORTED)
            {
                COM_PRINT(_T("支持多结果集
    "));
            }else if (pDBPropset[0].rgProperties[0].vValue.intVal & DBPROPVAL_MR_NOTSUPPORTED)
            {
                COM_PRINT(_T("不支持多结果集
    "));
                goto __CLEAR_UP;
            }
            else
            {
                COM_PRINT(_T("未知
    "));
                goto __CLEAR_UP;
            }
        }
        
        bRet = TRUE;
    __CLEAR_UP:
        SAFE_RELSEASE(pIDBInitialize);
        SAFE_RELSEASE(pIDBProperties);
        SAFE_RELSEASE(pIGetDataSource);
    
        CoTaskMemFree(pDBPropset[0].rgProperties);
        CoTaskMemFree(pDBPropset);
    
        return bRet;
    }
    
    // 执行sql语句并返回多结果集对象
    BOOL ExecSQL(LPOLESTR lpSQL, IOpenRowset *pIOpenRowset, IMultipleResults* &pIMultipleResults)
    {
        COM_DECLARE_BUFFER();
        COM_DECLARE_INTERFACE(IDBCreateCommand);
        COM_DECLARE_INTERFACE(ICommandText);
        COM_DECLARE_INTERFACE(ICommandProperties);
    
        BOOL bRet = FALSE;
        DBPROP dbProp[2] = {0};
        DBPROPSET dbPropset[1] = {0};
        dbProp[0].colid = DB_NULLID;
        dbProp[0].dwOptions = DBPROPOPTIONS_REQUIRED;
        dbProp[0].dwPropertyID = DBPROP_UPDATABILITY;
        dbProp[0].vValue.vt = VT_I4;
        dbProp[0].vValue.intVal = DBPROPVAL_UP_CHANGE | DBPROPVAL_UP_DELETE | DBPROPVAL_UP_INSERT;
    
        //设置SQL语句
        HRESULT hRes = pIOpenRowset->QueryInterface(IID_IDBCreateCommand, (void**)&pIDBCreateCommand);
        COM_SUCCESS(hRes, _T("查询接口IDBCreateCommand失败,错误码:%08x
    "), hRes);
        hRes = pIDBCreateCommand->CreateCommand(NULL , IID_ICommandText, (IUnknown**)&pICommandText);
        COM_SUCCESS(hRes, _T("创建接口ICommandText失败,错误码:%08x"), hRes);
        hRes = pICommandText->SetCommandText(DBGUID_DEFAULT, lpSQL);
        COM_SUCCESS(hRes, _T("设置SQL语句失败,错误码为:%08x
    "), hRes);
    
        //设置属性
        hRes = pICommandText->QueryInterface(IID_ICommandProperties, (void**)&pICommandProperties);
        COM_SUCCESS(hRes, _T("查询接口ICommandProperties接口失败,错误码:%08x
    "), hRes);
    
        //执行SQL语句
        hRes = pICommandText->Execute(NULL, IID_IMultipleResults, NULL, NULL, (IUnknown**)&pIMultipleResults);
        COM_SUCCESS(hRes, _T("执行SQL语句失败,错误码:%08x
    "), hRes);
    
        bRet = TRUE;
    __CLEAR_UP:
        SAFE_RELSEASE(pIDBCreateCommand);
        SAFE_RELSEASE(pICommandText);
        SAFE_RELSEASE(pICommandProperties);
    
        return bRet;
    }
    
    int _tmain(int argc, TCHAR *argv[])
    {
        CoInitialize(NULL);
        COM_DECLARE_BUFFER();
        COM_DECLARE_INTERFACE(IOpenRowset);
        COM_DECLARE_INTERFACE(IMultipleResults);
        COM_DECLARE_INTERFACE(IRowset);
    
        LPOLESTR pSQL = OLESTR("Select * From aa26 Where Left(aac031,2) = '11';
                               Select * From aa26 Where Left(aac031,2) = '32';
                               Select * From aa26 Where Left(aac031,2) = '21';");
    
        if (!CreateSession(pIOpenRowset))
        {
            goto __EXIT;
        }
    
        if (!SupportMultipleRowsets(pIOpenRowset))
        {
            goto __EXIT;
        }
    
        if (!ExecSQL(pSQL, pIOpenRowset, pIMultipleResults))
        {
            goto __EXIT;
        }
    
        //循环取结果集
        while (TRUE)
        {
            HRESULT hr = pIMultipleResults->GetResult(NULL, DBRESULTFLAG_DEFAULT, IID_IRowset, NULL, (IUnknown**)&pIRowset);
            if (hr != S_OK)
            {
                break;
            }
            //后面的代码就是针对每个结果集来进行列的绑定与数据输出,在这就不列举出来了
    __CLEAR_UP:
            CoTaskMemFree(pdbColumn);
            CoTaskMemFree(pColumsName);
            FREE(pDBBinding);
            FREE(pData);
            pIAccessor->ReleaseAccessor(hAccessor, NULL);
            SAFE_RELSEASE(pIColumnsInfo);
            SAFE_RELSEASE(pIAccessor);
            SAFE_RELSEASE(pIRowset);
    
            _tsystem(_T("PAUSE"));
        }
    
    __EXIT:
        SAFE_RELSEASE(pIOpenRowset);
        SAFE_RELSEASE(pIMultipleResults);
    
        CoUninitialize();
        return 0;
    }
    

    最后贴出例子完整代码的链接:
    [源代码查看](https://gitee.com/masimaro/codes/vypocjnkabdu6wz8gfh0m36# MultipleResults)


  • 相关阅读:
    SignalR
    log4net
    nginx
    mongodb
    uni-app监听软键盘是否弹起,ios不支持
    js插件开发兼容commonJS、AMD、CDM的UMD写法
    uni-app 实现后端返回的图片文件流转base64
    input输入框限制只能输入数字和一个小数点
    Uni-app工程转vue-cli工程步骤
    H5 移动端开发注意事项
  • 原文地址:https://www.cnblogs.com/lanuage/p/8585878.html
Copyright © 2011-2022 走看看