Export (0) Print
Expand All
Expand Minimize

AppendChunk and GetChunk Methods Example (VC++)

This example uses the AppendChunk and GetChunk methods to fill an image field with data from another record.

// BeginAppendChunkCpp.cpp
// compile with: /EHsc /c
#import "msado15.dll" no_namespace rename("EOF", "EndOfFile")

#define ChunkSize 100

#include <ole2.h>
#include <stdio.h>
#include "conio.h"
#include "malloc.h"
#include "icrsint.h"

// extracts pubid, prinfo.
class CPubInfoRs : public CADORecordBinding {
   BEGIN_ADO_BINDING(CPubInfoRs)
   ADO_VARIABLE_LENGTH_ENTRY2(1, adVarChar, m_sz_pubid, sizeof(m_sz_pubid), l_pubid, TRUE)
   ADO_VARIABLE_LENGTH_ENTRY2(3, adVarChar, m_sz_prinfo, sizeof(m_sz_prinfo), l_prinfo, TRUE)
   END_ADO_BINDING()

public:
   CHAR m_sz_pubid[10];
   ULONG l_pubid;
   CHAR m_sz_prinfo[200];
   ULONG l_prinfo;    
};

//Function declarations
inline void TESTHR(HRESULT x) { if FAILED(x) _com_issue_error(x); };
void AppendChunkX();
void PrintProviderError(_ConnectionPtr pConnection);

inline int myscanf(char* strDest, int n) {    
   char strExBuff[10];
   char* pstrRet = fgets(strDest, n, stdin);

   if (pstrRet == NULL)
      return 0;

   if (!strrchr(strDest, '\n'))
      // Exhaust the input buffer.
      do {
         fgets(strExBuff, sizeof(strExBuff), stdin);
      } while (!strrchr(strExBuff, '\n'));
   else
      // Replace '\n' with '\0'
      strDest[strrchr(strDest, '\n') - strDest] = '\0';

   return strlen(strDest);
}
inline char* mygets(char* strDest, int n) {    
   char strExBuff[10];
   char* pstrRet = fgets(strDest, n, stdin);

   if (pstrRet == NULL)
      return NULL;

   if (!strrchr(strDest, '\n'))
      // Exhaust the input buffer.
      do {
         fgets(strExBuff, sizeof(strExBuff), stdin);
      } while (!strrchr(strExBuff, '\n'));
   else
      // Replace '\n' with '\0'
      strDest[strrchr(strDest, '\n') - strDest] = '\0';

   return pstrRet;
}

int main() {
   HRESULT  hr = S_OK;

   if (FAILED(::CoInitialize(NULL)))
      return -1;

   AppendChunkX();

   ::CoUninitialize();
}

void AppendChunkX() {
   // Define ADO object pointers, initialize pointers on define. These are in the ADODB::  namespace.
   _RecordsetPtr pRstPubInfo = NULL;
   _ConnectionPtr pConnection = NULL;
   char * token1;

   // Define other variables
   IADORecordBinding *picRs = NULL;   // Interface Pointer declared.(VC++ Extensions)
   CPubInfoRs pubrs;   // C++ class object   

   HRESULT hr = S_OK;
   _bstr_t strCnn("Provider='sqloledb'; Data Source='My_Data_Source'; Initial Catalog='pubs'; Integrated Security='SSPI';");

   _bstr_t strMessage,strPubID,strPRInfo;
   _variant_t varChunk;
   long lngOffSet,lngLogoSize;
   char pubId[50];
   lngOffSet = 0;

   UCHAR chData;
   SAFEARRAY FAR *psa;
   SAFEARRAYBOUND rgsabound[1];
   rgsabound[0].lLbound = 0;
   rgsabound[0].cElements = ChunkSize;

   try {
      // Open a Connection.
      TESTHR(pConnection.CreateInstance(__uuidof(Connection)));
      hr = pConnection->Open(strCnn, "", "", adConnectUnspecified);

      TESTHR(hr= pRstPubInfo.CreateInstance(__uuidof(Recordset)));  

      pRstPubInfo->CursorType = adOpenKeyset;
      pRstPubInfo->LockType = adLockOptimistic;

      hr = pRstPubInfo->Open("pub_info", _variant_t((IDispatch*)pConnection,true),
                              adOpenKeyset, adLockOptimistic, adCmdTable);

      // Open an IADORecordBinding interface pointer for Binding Recordset to a class    
      TESTHR(pRstPubInfo->QueryInterface(__uuidof(IADORecordBinding), (LPVOID*)&picRs));

      // Bind the Recordset to a C++ Class here    
      TESTHR(picRs->BindToRecordset(&pubrs));

      // Display the available logos here
      strMessage = "Available logos are: " + (_bstr_t)"\n\n";
      printf(strMessage);
      int Counter = 0;
      while (!(pRstPubInfo->EndOfFile)) { 
         printf("\n%s", pubrs.m_sz_pubid);
         printf("\n%s", strtok_s(pubrs.m_sz_prinfo, ",", &token1));

         // Display 5 records at a time and wait for user to continue..
         if (++Counter >= 5) {
            Counter = 0;
            printf("\nPress any key to continue...");
            _getch();
         }
         pRstPubInfo->MoveNext(); 
      }

      // Prompt For a Logo to Copy
      printf("\nEnter the ID of a logo to copy: ");
      myscanf(pubId, sizeof(pubId));
      strPubID = pubId;

      // Copy the logo to a variable in chunks
      pRstPubInfo->Filter = "pub_id = '"  + strPubID + "'";
      lngLogoSize = pRstPubInfo->Fields->Item["logo"]->ActualSize;

      // Create a safe array to store the array of BYTES  
      rgsabound[0].cElements = lngLogoSize;
      psa = SafeArrayCreate(VT_UI1, 1, rgsabound);

      long index1 = 0;
      while (lngOffSet < lngLogoSize) {
         varChunk = pRstPubInfo->Fields->Item["logo"]->GetChunk(ChunkSize);

         // Copy the data only upto the Actual Size of Field.  
         for (long index = 0 ; index <= (ChunkSize - 1) ; index++) {
            hr = SafeArrayGetElement(varChunk.parray, &index, &chData);
            if (SUCCEEDED(hr)) {
               // Take BYTE by BYTE and advance Memory Location
               hr = SafeArrayPutElement(psa, &index1, &chData); 
               index1++;
            }
            else
               break;
         }
         lngOffSet = lngOffSet + ChunkSize;
      }
      lngOffSet = 0;

      printf("Enter a new Pub Id: ");
      myscanf(pubrs.m_sz_pubid, sizeof(pubrs.m_sz_pubid));
      strPubID = pubrs.m_sz_pubid;
      printf("Enter descriptive text: " );
      mygets(pubrs.m_sz_prinfo, sizeof(pubrs.m_sz_prinfo));

      pRstPubInfo->AddNew();
      pRstPubInfo->Fields->GetItem("pub_id")->PutValue(strPubID);
      pRstPubInfo->Fields->GetItem("pr_info")->PutValue(pubrs.m_sz_prinfo);

      // Assign the Safe array  to a variant. 
      varChunk.vt = VT_ARRAY|VT_UI1;
      varChunk.parray = psa;
      hr = pRstPubInfo->Fields->GetItem("logo")->AppendChunk(varChunk); 

      // Update the table 
      pRstPubInfo->Update();

      lngLogoSize = pRstPubInfo->Fields->Item["logo"]->ActualSize;

      // Show the newly added record.
      printf("New Record : %s\n Description : %s\n Logo Size : %s",
         pubrs.m_sz_pubid,
         pubrs.m_sz_prinfo,(LPCSTR)(_bstr_t)pRstPubInfo->Fields->
         Item["logo"]->ActualSize);

      // Delete new record because this is demonstration.
      pConnection->Execute("DELETE FROM PUB_INFO WHERE pub_id = '"
         + strPubID +"'", NULL,adCmdText);
   }
   catch(_com_error &e) {
      // Notify the user of errors if any.
      _bstr_t bstrSource(e.Source());
      _bstr_t bstrDescription(e.Description());

      PrintProviderError(pConnection);
      printf("Source : %s \n Description : %s\n", (LPCSTR)bstrSource,
         (LPCSTR)bstrDescription);
   }

   // Clean up objects before exit.
   if (pRstPubInfo)
      if (pRstPubInfo->State == adStateOpen)
         pRstPubInfo->Close();
   if (pConnection)
      if (pConnection->State == adStateOpen)
         pConnection->Close();
}

void PrintProviderError(_ConnectionPtr pConnection) {
   // Print Provider Errors from Connection object.
   // pErr is a record object in the Connection's Error collection.
   ErrorPtr pErr = NULL;
   long nCount = 0;
   long i = 0;

   if ( (pConnection->Errors->Count) > 0) {
      nCount = pConnection->Errors->Count;
      // Collection ranges from 0 to nCount -1.
      for (i = 0 ; i < nCount ; i++) {
         pErr = pConnection->Errors->GetItem(i);
         printf("\t Error number: %x\t%s", pErr->Number, (LPCSTR) pErr->Description);
      }
   }
}
Show:
© 2014 Microsoft