AddNew on an empty Recordset fails in MS C++ AddNew Example

AddNew on an empty Recordset fails in MS C++ AddNew Example

Post by Robert Ker » Sat, 08 Apr 2000 04:00:00



I'm trying to create a new record in an empty recordset.  Each time I try to
call AddNew I get an error.

I'm using VC 6.0 with the ADO C++ Extensions.

The error I get is:     0x80040E21
This translates to:    Errors Occurred
                                  (Duh! The guy that came up with that one
should be given an award....)

To test this functionality, I was using one of Microsoft's examples
verbatum.  (i.e. if you enter their code as it is written in their help file
and point it at an empty table in a database then the code fails!!!)

The code section I started with is the 'AddNew' example given in MS's MDAK
2.5 visual C++ examples.  The only change I made was to point it to my SQL
Server database.  The example works if you use a populated database table,
but
fails on an empty database table.  I've tracked it down to learn enough to
know
that if the recordset is empty (i.e. the Open command returns no rows from a
table with rows, or the opened table is empty) then the AddNew command
fails.

Rob Kerr
Digital Sandbox

The full extent of the code gets a bit long, but here it is (ignore the
file:// junk):

#import "C:\Program Files\Common Files\System\ADO\msado15.dll" \
    no_namespace rename("EOF", "EndOfFile")

#include <ole2.h>
#include <stdio.h>
#include "conio.h"
#include "AddNewX.h"

/* File declaration */
inline void TESTHR(HRESULT x) {if FAILED(x) _com_issue_error(x);};
void AddNewX(void);
void PrintProviderError(_ConnectionPtr pConnection);

///////////////////////////////////////////////////////////
//                                                       //
//      Main Function                                    //
//                                                       //
///////////////////////////////////////////////////////////
void main()
{
    if(FAILED(::CoInitialize(NULL)))
        return;

    AddNewX();

    ::CoUninitialize();

}

///////////////////////////////////////////////////////////
//                                                       //
//      AddNewX Function                                 //
//                                                       //
///////////////////////////////////////////////////////////
void  AddNewX(void)
{
    // Define ADO object pointers.
    // Initialize pointers on define.
    _RecordsetPtr  pRstEmployees = NULL;
    _ConnectionPtr pConnection   = NULL;

    /* Define Other variables
    IADORecordBinding   *picRs = NULL;    /* Interface Pointer declared. */
    CEmployeeRs emprs;                                /* C++ class object */
    HRESULT hr = S_OK;

    _bstr_t strCnn("Provider=sqloledb;Data Source=(local); Initial
Catalog=spdbpro;User Id=sa;Password=;");
    _bstr_t strId;
    _bstr_t strMessage;

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

        /* Open employee table. */
        TESTHR(pRstEmployees.CreateInstance(__uuidof(Recordset)));

        /* You have to explicitly pass the Cursor type and LockType */
        /* to the Recordset here. */
        pRstEmployees->Open("employee",
            _variant_t((IDispatch *) pConnection,true),
            adOpenKeyset,adLockOptimistic,adCmdTable);

        /* Open an IADORecordBinding interface pointer which we'll use */
        /* for Binding Recordset to a class. */
        TESTHR(pRstEmployees->QueryInterface(
                __uuidof(IADORecordBinding),(LPVOID*)&picRs));

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

        // Get data from the user.The employee id must be formatted as
        // first,middle and last initial,five numbers,then M or F to
        // signify the gender.For example,the employee id for
        // Bill A. Sorensen would be "BAS55555M".

        printf("Enter Employee Id: ");scanf("%s",emprs.m_sz_empid);
        strId = emprs.m_sz_empid;
        printf("Enter First Name: ");scanf("%s",emprs.m_sz_fname);
        printf("Enter Last Name:");scanf("%s",emprs.m_sz_lname);

        /* Proceed if the user actually entered something */
        /* for the id, the first and the last name. */

        if(strcmp(emprs.m_sz_empid,"") &&
           strcmp(emprs.m_sz_fname,"") &&
           strcmp(emprs.m_sz_lname,""))
        {
            /* This adds a new record to the table */
            /* if (FAILED(hr = picRs->AddNew(&emprs))) */
            /* _com_issue_error(hr); */
            TESTHR(picRs->AddNew(&emprs));

            /* Show the newly added data */
            printf("New Record: %s  %s  %s \n",
                emprs.lemp_empidStatus == adFldOK ?
                emprs.m_sz_empid : "<NULL>",
                emprs.lemp_fnameStatus == adFldOK ?
                emprs.m_sz_fname : "<NULL>",
                emprs.lemp_lnameStatus == adFldOK ?
                emprs.m_sz_lname : "<NULL>");
        }
        else
            printf("Please enter an employee id, first name "
                "and last name.\n");

        /* Delete the new record because this is a demonstration. */
        pConnection->Execute("DELETE FROM EMPLOYEE WHERE emp_id ="
            "'" + strId + "'",NULL,adCmdText);

        /* Release the IADORecordset Interface here */
        if (picRs)
            picRs->Release();

        // Clean up objects before exit.
        pRstEmployees->Close();
        pConnection->Close();
    }

    catch(_com_error &e)
    {
        // Notify the user of errors if any.
        _variant_t vtConnect = pRstEmployees->GetActiveConnection();

        // GetActiveConnection returns connect string if connection
        // is not open, else returns Connection object.
        switch(vtConnect.vt)
        {
            case VT_BSTR:
                printf("Error:\n");
                printf("Code = %08lx\n", e.Error());
                printf("Message = %s\n", e.ErrorMessage());
                printf("Source = %s\n", (LPCSTR) e.Source());
                printf("Description = %s\n", (LPCSTR) e.Description());
                break;
            case VT_DISPATCH:
                PrintProviderError(vtConnect);
                break;
            default:
                printf("Errors occured.");
                break;
        }
    }

}

///////////////////////////////////////////////////////////
//                                                       //
//      PrintProviderError Function                      //
//                                                       //
///////////////////////////////////////////////////////////

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("\n\t Error number: %x\t%s",
                pErr->Number, (LPCSTR)pErr->Description);
        }
    }

}

AddNewX.h:

#include "icrsint.h"

/* This Class extracts empid, fname and lastname */

class CEmployeeRs : public CADORecordBinding
{
BEGIN_ADO_BINDING(CEmployeeRs)

    /* Column empid is the 1st field in the recordset */

    ADO_VARIABLE_LENGTH_ENTRY2(1, adVarChar, m_sz_empid,
         sizeof(m_sz_empid), lemp_empidStatus, TRUE)

    ADO_VARIABLE_LENGTH_ENTRY2(2, adVarChar, m_sz_fname,
         sizeof(m_sz_fname), lemp_fnameStatus, TRUE)

    ADO_VARIABLE_LENGTH_ENTRY2(4, adVarChar, m_sz_lname,
         sizeof(m_sz_lname), lemp_lnameStatus, TRUE)

END_ADO_BINDING()

public:

   CHAR  m_sz_empid[10];
   ULONG lemp_empidStatus;
   CHAR   m_sz_fname[40];
   ULONG  lemp_fnameStatus;
   CHAR   m_sz_lname[41];
   ULONG  lemp_lnameStatus;

};

 
 
 

AddNew on an empty Recordset fails in MS C++ AddNew Example

Post by RowingWo » Sun, 16 Apr 2000 04:00:00


Hello Robert,

Here are my two cents:  the MS ADO wrapper classes suck.....!  In particular I
hate how they bind variables to the recordset -- I'm always changing my
database designs, and tend to avoid ordinal mapping for fear it will break when
I change the database.

I've got a wrapper class with an AddNew() example on my website at
www.ADOPro.com.  Download the library and compile the sample....if you have any
problems let me know & I'll try to help you through them....

Paul

 
 
 

1. Example of Recordset.AddNew for MS Access

Somebody, pls. send me or post here a short, 10-15-lines-long (yet
detailed enough) example of use of ADODB.Recordset.AddNew that WORKS
with MDAC 2.1 and MS Access database.

My problem is that in runtime I get error from the server that "method
or property not supported: objRecordSet.AddNew". I was able to create
instance with Server.CreateObject ("ADODB.Recordset") and assign
property values for LockType (tried adLockPessimistic and
adLockOptimistic), CursorType (tried everything), Source and
ActiveConnection. If I call AddNew later, get the above error.

Please help.
Maxim

Sent via Deja.com http://www.deja.com/
Before you buy.

2. uvodbc DBCAPERR - UCI Error on CONVERT.SQL FILES in some accounts

3. ADO Extensions-AddNew to an Empty Table Failed????

4. Change field size in a database ?

5. IADORecordBinding.AddNew() fails on empty table

6. Using BCP with French text

7. Help: AddNew record to an empty recordset

8. PB with Ansi / Non Ansi Db

9. Addnew on empty disconnected recordset

10. Help!!! : AddNew returns error on empty recordset

11. AddNew on an empty recordset

12. Help: operation is cancelled by associated object (data.recordset.addnew of an empty table)

13. ADO cancelupdate after addnew on an empty recordset