How To Implement Visual C++ COM Objects Returning Recordsets (225131)



The information in this article applies to:

  • Microsoft Active Server Pages
  • ActiveX Data Objects (ADO)
  • Microsoft Visual C++, 32-bit Enterprise Edition 5.0
  • Microsoft Visual C++, 32-bit Enterprise Edition 6.0
  • Microsoft Visual C++, 32-bit Professional Edition 5.0
  • Microsoft Visual C++, 32-bit Professional Edition 6.0
  • Microsoft Visual C++, 32-bit Learning Edition 6.0
  • Microsoft Internet Information Server 4.0
  • Microsoft Internet Information Server 5.0
  • Microsoft Data Access Components 2.5

This article was previously published under Q225131

SUMMARY

This article describes, by example, how to implement a Visual C++ Component Object Model (COM) object that returns a recordset to Active Server Pages (ASP).

Implementing this incorrectly can result in memory leaks or one of the following errors:
The operation requested by the application is not allowed if the object is closed.

-or-

Type Mismatch

-or-

error 'ASP 0115' - A trappable error occured in an external object

MORE INFORMATION

Use the following steps to implement a method that returns a recordset from a Visual C++ COM object to Active Server Pages.
  1. Create an ATL DLL project called PassRs.
  2. Insert an ATL object named PassRsObj.
  3. Add a method with the following information:
    Method Name: TestMethod
    Parameters : [out, retval] LPDISPATCH* ppRecordset
    					
  4. Include the following line in the object's implementation file:
    #import "msado15.dll" no_namespace rename("EOF", "adoEOF")
    					
  5. Implement the method as follows:

    Note You must change UID=<username> and pwd=<strong password> to the correct values before you run this code. Make sure that UID has the appropriate permissions to perform this operation on the database.
    STDMETHODIMP CPassRsObj::TestMethod(LPDISPATCH *ppRecordset )
    {
        _ConnectionPtr pConn;
        _RecordsetPtr pRs;
    	
        pConn.CreateInstance(__uuidof(Connection));
        pRs.CreateInstance(__uuidof(Recordset));
    
        pConn->Open("DSN=pubs;uid=<username>;pwd=<strong password>;", (BSTR) NULL, (BSTR) NULL, -1);
    
        //Client side cursor is required for disconnected recordsets
        pRs->CursorLocation = adUseClient;
    
        pRs->Open( "select * from authors",
                   pConn.GetInterfacePtr(),
                   adOpenKeyset, adLockOptimistic, -1);
    
        // Disconnect the recordset
        pRs->PutRefActiveConnection(NULL);
    
        //Clone the recordset. 
        //NOTE: Recordset to be cloned must support bookmarks
        pRs->Clone(adLockOptimistic)->QueryInterface(IID_IDispatch, (void**) ppRecordset);
    
        pRs->Close();
        pConn->Close();
    
        pRs = NULL;
        pConn = NULL;	
    
        return S_OK;
    }
    					
  6. Create an ASP page with the following code:
    <%
    Dim rsTest, oTestPassRs
    
    Set oTestPassRs = Server.CreateObject("PassRs.PassRsObj")
    Set rsTest = oTestPassRs.TestMethod()
    
    Do 
       Response.Write ( "Value in Record = " & rsTest(1) & "<BR>" )
       rsTest.MoveNext
    Loop until rsTest.EOF
    
    rsTest.Close
    Set rsTest = Nothing
    Set oTestPassRs = Nothing
    %>
    					

REFERENCES

For additional information, please see the following articles in the Microsoft Knowledge Base:

184397 How To Getting ADO Disconnected Recordsets in VBA/C++/Java

193515 PRB: Update of Same Record 2x w/Disconnect ADO Recordset Fails

224424 How To Implement Visual Basic COM Objects Returning Recordsets


Modification Type:MinorLast Reviewed:7/1/2004
Keywords:kbCodeSnippet kbDatabase kberrmsg kbhowto KB225131