Solved

CRecordset catch and error

Posted on 2002-03-06
30
1,410 Views
Last Modified: 2013-11-20
Using ODBC CRecordset in an application.

While debugging my application I tried using a try/catch block but the application throws an exception while updating a record set at this point (the MFC file : dbcore.cpp line 3579 ) and terminates before my catch statement.

ThrowDBException((RETCODE)(lRowsAffected == 0 ?AFX_SQL_ERROR_NO_ROWS_AFFECTED :AFX_SQL_ERROR_MULTIPLE_ROWS_AFFECTED));

Inspecting the value of lRowsAffected I find it is  == 0.

This is the block of code that is used to update.
for (int a=0;a<arsize;a++)
     {
          //     CustAccounts.SetAbsolutePosition( a+1);
          tempStorage = AccountList.GetAt(a);

//note: change struct var from type bool to char (BYTE)
          if( tempStorage.UseAct == true)
               use = '1';
          else
               use = '0';

          CustAccounts.Edit();    
          if (     CustAccounts.m_bStatement !=  use)
          {
               CustAccounts.m_bStatement =  use;
               try{
                    CustAccounts.Update();
               }
               catch(CDBException * e)
               {
                    CString errmsg = "The exception thrown :" + e->m_strError;
                    AfxMessageBox( errmsg,   MB_ICONSTOP    );
                    e->Delete();              
               }
          }
          CustAccounts.MoveNext();
          WinShow->Bar->SetPos(a);
     }
Why doesn't my catch statement handle the exception rather than just the program terminating?
I have 6 data sets and the application works on all but 1 of them (which throws the exception).
I would like to retrieve more detailed information as to why the exception is being thrown (ie why no columns are updated) or at least some reason why.
No records are deleted (they all appear in the originating software) and running a data integrity check on the originating software does not reveal any errors.
Any suggestions??
Txs
 
0
Comment
Question by:dooley090698
  • 15
  • 10
  • 3
  • +1
30 Comments
 
LVL 6

Expert Comment

by:Triskelion
ID: 6844492
Your use of 'use' may be at fault.
You're not setting them at 0 and 1 but '0' and '1', which will always produce 'true'.

0
 
LVL 6

Expert Comment

by:Triskelion
ID: 6844510
0=0  // or false
1=1  // or true
'1' = 0x31 // still true
'0' = 0x30 // still true
0
 

Author Comment

by:dooley090698
ID: 6845894
the m_bStatement variable is of type BYTE.
My structure which conatins the flag setting is of type bool
The prgeam worked with the bool operator except for the data set in question so the "use" code was simply to try using a char instead of bool operator.
Am I off base here???
0
 
LVL 6

Expert Comment

by:Triskelion
ID: 6845940
Have you checked IsEOF() and IsBOF() to make sure your position is good?

Did you run this in a debugger to watch the bad statement happen?
0
 
LVL 23

Expert Comment

by:Roshan Davis
ID: 6846374
Put "CustAccounts.Edit();" inside the if condition.

GOOD LUCK
0
 
LVL 23

Expert Comment

by:Roshan Davis
ID: 6846375
That is

         if (     CustAccounts.m_bStatement !=  use)
         {
     CustAccounts.Edit();    
              CustAccounts.m_bStatement =  use;
              try{
                   CustAccounts.Update();
              }
              catch(CDBException * e)
              {
                   CString errmsg = "The exception thrown :" + e->m_strError;
                   AfxMessageBox( errmsg,   MB_ICONSTOP    );
                   e->Delete();              
              }
         }
         CustAccounts.MoveNext();

GOOD LUCK
0
 

Author Comment

by:dooley090698
ID: 6846389
Triskelion... I traced the record that was creating the error right into the MFC's..that's how I came up wotht the fact the exception seemed to be thrown since no records were updated.
A quick watch inspection of the record displayed the correct data for the record being worked on.
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6846675
I recall having some problems catching an exception on an update error (it can happen when the table is locked or if you have turned on bulk op or the SELECT statement was wrong).  I ended up with a try/catch in a CRecordset-derived base class with an override on the Update() fn (and the try/catch in that base class).

Is it possible that some other (nested) exception is occurring?  You are only catching CDBException.

-- Dan
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6846692
In this google thread,

http://groups.google.com/groups?hl=en&threadm=333BE49A.6F1C%40world.std.com&rnum=4&prev=/groups%3Fq%3DAFX_SQL_ERROR_NO_ROWS_AFFECTED%26hl%3Den%26btnG%3DGoogle%2BSearch

The author claims the problem is a missing string resource (when it tries to generate the exception txt)... and that rings a bell with me
.

-- Dan
0
 

Author Comment

by:dooley090698
ID: 6854575
Damn frustrating!!!
This program works flawlessly on 3 out of 5 data sets I have to work with.
2 of the sets return the exception error which I can't seem to catch. Program halts in DBCore before it returns


This code snippet is in Dbcore.cpp line 3562    
the var OptimizeBulkAdd = Hex 4000

SDWORD lRowsAffected = 0;

     AFX_SQL_SYNC(::SQLRowCount(m_hstmtUpdate, &lRowsAffected));

//Inspecting I find that  nRetCode=0 and  lRowsAffected  = 0

     if (!Check(nRetCode) || lRowsAffected == -1)
     {
          // Assume 1 row affected if # rows affected can't be determined
          lRowsAffected = 1;
     }
     else
     {
          if (lRowsAffected != 1)
          {
#ifdef _DEBUG
               if (afxTraceFlags & traceDatabase)
                    TRACE1("Warning: %u rows affected by update operation (expected 1).\n",
                         lRowsAffected);
#endif
               ThrowDBException((RETCODE)(lRowsAffected == 0 ?
                    AFX_SQL_ERROR_NO_ROWS_AFFECTED :
                    AFX_SQL_ERROR_MULTIPLE_ROWS_AFFECTED));
          }
     }
     m_strUpdateSQL.Empty();
}

Any suggestions as to why SQLRowCount(m_hstmtUpdate, &lRowsAffected) returns 0 for rows affected??
Where can I look??
This is just a simple field updating program..is there another way rather than using the CRecordsets??
0
 

Author Comment

by:dooley090698
ID: 6854576
Damn frustrating!!!
This program works flawlessly on 3 out of 5 data sets I have to work with.
2 of the sets return the exception error which I can't seem to catch. Program halts in DBCore before it returns


This code snippet is in Dbcore.cpp line 3562    
the var OptimizeBulkAdd = Hex 4000

SDWORD lRowsAffected = 0;

     AFX_SQL_SYNC(::SQLRowCount(m_hstmtUpdate, &lRowsAffected));

//Inspecting I find that  nRetCode=0 and  lRowsAffected  = 0

     if (!Check(nRetCode) || lRowsAffected == -1)
     {
          // Assume 1 row affected if # rows affected can't be determined
          lRowsAffected = 1;
     }
     else
     {
          if (lRowsAffected != 1)
          {
#ifdef _DEBUG
               if (afxTraceFlags & traceDatabase)
                    TRACE1("Warning: %u rows affected by update operation (expected 1).\n",
                         lRowsAffected);
#endif
               ThrowDBException((RETCODE)(lRowsAffected == 0 ?
                    AFX_SQL_ERROR_NO_ROWS_AFFECTED :
                    AFX_SQL_ERROR_MULTIPLE_ROWS_AFFECTED));
          }
     }
     m_strUpdateSQL.Empty();
}

Any suggestions as to why SQLRowCount(m_hstmtUpdate, &lRowsAffected) returns 0 for rows affected??
Where can I look??
This is just a simple field updating program..is there another way rather than using the CRecordsets??
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6855164
Show the code that you use to open the CDatabase object.

Show the code that you use to open the CRecordset object.  Include all relevant values including strFilter etc.

Are you closing the CRecordset object that you used to fill the a collection before you start the update cycle?

>>is there another way rather than using the CRecordsets??
Yes, but CRecordsets are the easiest for cycling through a set of records and for updating many fields of a record at once at once.

If you want, you can simply build an SQL statment and use CDatabase::ExecuteSQL().  For instance:

CString sSQL;
sSQL.Format(
        "UPDATE MyTable SET sLastName='%s' "
        "WHERE nCustIdx=%d",
        (LPCSTR)sLastName,  // some local variables
        nCurCustIdx
);

try {
    mMyDb->ExecuteSQL( sSQL );
}
catch( ... etc ...

}

-- Dan
0
 

Author Comment

by:dooley090698
ID: 6857209
Dan,
Here is the code to open the database and update the recordsets.
The array of structures I use is loaded from the customer database by simply opening the recordset and sequentially parsing each record and plugging the relevant data into the structure.
Updating is simply the reverse procedure (parsing the array and the recordset and updating the flags as required).
The original (Simply Accounting) database is created using DAO but I can't seem to create recordsets for DAO as the file extension is sdb instead of mdb and if I simply change sdb to mdb I get a "not a valid Access" message so I went with ODBC.
I can view and edit the tables in MSAccess with a command line in a shortcut to MSAccess .
I should also mention that I can read/write to any of the other tables in the database, just this particular table (customers) is giving me this head ache yet the originating software doesn't report any errors and works just fine on the tables.
The program halts at the first table being updated whether it be at the beginning of the table or 1/3 of the way into it.
Also I have 5 data sets from clients that I am playing with and it works flawlessly on 3 of them yet fails on the other two. One of the sets it works on contains 2300 records, the set s it fails on contain only a few hundred or so, so size isn't the problem.
I ran into this problem before and overcame it by recreating the customer table but that's a REAL hassle (cause it was the 2300 customer data set ! )
Even if I can get some idea as to why the SQL call returns zero for columns to update I'd be happy cause then I'd at least have some idea as to why it fails on some data sets and not others!
I REALLY appreciate you taking the time to help me out here and if we can get this sorted out it's gotta be worth a hell of a lot more than 100 points!!
PS..how can I get more points?? I've been stingy cause I'm running out!!
Txs again for ALL your help (now and in the past).


bool SData::OpenDataBase()
{
      // First part of the connection to a recordset, Add file name after
      // remeber to watch the length of the file name inserted into the connection string
      
      AFX_MANAGE_STATE(AfxGetStaticModuleState());
      
      // m_db is pointer to CDatabase retined in base SData.h This file is SData.cpp
      if (m_db-> IsOpen( ))
            m_db->Close();
      
    ConPath = "ODBC;DSN=Simply Accounting: ";
      CFileDialog FOpen (TRUE,"*.sdb","*.sdb",OFN_HIDEREADONLY,"Simply Data |*.sdb ||");
      
      if (FOpen.DoModal()==IDOK)
      {
            Filename = FOpen.GetFileName(); // data source file
            PathName =FOpen.GetPathName( ) ;// data source path for diplsay purposes only
            
            // If data source name > 13 returns a "name too long" error
            if (Filename.GetLength() > 13)
                  Filename = Filename.Left(13);
            
            // Make the ODBC connection path
            ConPath=ConPath+Filename+";UID=sysadmin";      
            
            //global of ConPath that's inserted into each recordset's GetDefaultConnect() fn
            CONPATH = ConPath;
            
            //Open data base
            m_db->Open( ConPath);
            rs_CompData ComapnyInfo( m_db);
            rs_CompShare CompShared( m_db);
            ComapnyInfo.Open( AFX_DB_USE_DEFAULT_TYPE);
            CompShared.Open( AFX_DB_USE_DEFAULT_TYPE);            
            // Formatting a date display see CTime fn's      
            CUDate =  CompShared.m_dtUDate;
            CoName = ComapnyInfo.m_sCompName;
            
            ComapnyInfo.Close();
            CompShared.Close();
            // Make sure that the data file sets are compatible with this version
            VerifyVerNo();
            return true;
      }
      else
            return false;      
}


void SRec::UpdateCustDataBase()
{
      // The progress bar dialog
      WinShow->ShowWindow(SW_SHOW);
      WinShow->Bar->SetRange(0,(short)NoCustAccts);
      
      /* Definition of fn that return the DB pointer from the inherited class
      CDatabase * SData::GetDB()
      {
      return m_db;
      }
      */
      rs_Customers CustAccounts (GetDB());
      
      // If Rec set fails to open return
      if ( ! CustAccounts. IsOpen()  )
            if (!CustAccounts.Open( AFX_DB_USE_DEFAULT_TYPE))
            {
                  MessageBox(0,"Error","ERROR OPENING CUST DATA BASE",MB_OK);
                  return;
            }
            // Get the size of the array of type struct AccountMaster
            int  arsize = AccountList.GetSize();
            // temp structure to hold data pulled from the array
            struct AccountMaster tempStorage;
            // variable of type BYTE as that's the type declared in the recordsets. Was using bool variable in structure
            //that works just as well as the BYTE . (ie failed on same database)
            BYTE use;
            WinShow->SetWindowText( "Updateing Customer Data Base");
            
            for (int a=0;a<arsize;a++)
            {
                  // extract the struct from the array to view.
                  tempStorage = AccountList.GetAt(a);
                  // if the flag is set to print then set to true else false
                  if( tempStorage.UseAct == true)
                        use = 1;
                  else
                        use = 0;
                  TRACE("Updating cust %s \n",tempStorage.ActName);
                  
                  // only change records if they need to be. Speeds up writing back to a huge data base
                  if (  CustAccounts.m_bStatement !=  use)
                  {
                        if (!CustAccounts.CanUpdate( ) )
                              AfxMessageBox("Cant Update " );
                        if ( CustAccounts.IsDeleted( ) )
                              AfxMessageBox("Deleted Record");
                        try{
                              CustAccounts.Edit();    
                        }
                        catch(CDBException * e)
                        {
                              CString errmsg = "Edit exception thrown :" + e->m_strError;
                              AfxMessageBox( errmsg,   MB_ICONSTOP    );
                              e->Delete();              
                        }
                        // set the recordset flag
                        CustAccounts.m_bStatement =  tempStorage.UseAct;
                        try{                        
                              if (! CustAccounts.Update() )
                                    AfxMessageBox("Update error");
                        }
                        catch(CDBException * e)
                        {
                              CString errmsg = "The exception thrown :" + e->m_strError;
                              AfxMessageBox( errmsg,   MB_ICONSTOP    );
                              e->Delete();              
                        }
                  }
                  // move to next record
                  CustAccounts.MoveNext();
                  WinShow->Bar->SetPos(a);
            }
            CustAccounts.Close();
            WinShow->ShowWindow(SW_HIDE);
}

So??
What do you think??

0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6857592
This is dangerous code and it indicates a misconception about the use of relational databases.  

Your implicit assumption is that if you read, say 20 records into a memory array, then you can read them again and update some or all of them at some future point just by cycling through using MoveNext and Edit and Update.

That is not how to update records.  You need to have a unique index value associated with each record.  Open or Requery the recordset with that index as the filter.  Then you will have a recordset containing a single record.  You can Edit and Update that recordset without causing errors.

Relational databases do not guarantee the absolute position of any record.  So when you first read the array, you may get records 1,2,3,4 but when you reopen, they may be in any order 2,3,4,1 and of course they could be 1,2,4 (where somebody else has deleted record 3).

-- Dan
0
 

Author Comment

by:dooley090698
ID: 6858333
Dan,
I’m not too sure I know what you mean.
The structure goes something like this:

Struct ActMaster{
int ActInx; //the index number of the acct
CString acName;// the customers acct
bool print ; // bool operator true if to print, false if no print
// and other various flags…
};

The  recordset is opened and sequentially read (using the MoveNext()  putting the required data (ActInx,acName etc) into this structure which is added to array.
The recordset is then closed.
The array is passed to various dialog boxes that are used to set the various flags.
The recordset is then opened again and since the order in the array would match the order in the recordset (the array itself is never sorted or rearranged) it stands to reason that array element  =  record read in (or at least so I thought!).ie 1st record read in = first array element,25 record read in  = 25 array element (taking into consideration of course arrays are 0 based)
Inspecting the data during debug I find the structure name does in fact match the record read in.
Is there an error on my reasoning and logic concerning the recordset being read in the same order both times?
Or does the MFC Recordset require more specific info (ie the index) to perform the update operation?
I’ll try re querying with the account index tonight to see if that solves the problem but I’d still like to know if my logic and reasoning are in error.
You are right when you say I display a lack of understanding of relational databases!!
Still trying to sort things out!
Thanks again for your efforts.


0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 49

Expert Comment

by:DanRollins
ID: 6859107
>>and since the order in the array would match the order in the recordset (the array itself is never sorted or rearranged) it stands to reason that ...

As I said, there is no guarantte that they will be in the same order on the second pass.  Simple example: A different program deletes one of the records.  But even if *ntoehring* like that happens, the database may find aa reason to cycle in a different order (another exampole: If there are some records already in a local cash, there is nothing that prevents it from feeding them back to you first while it goesd and fetches the other records.

=--=-=

So, what you should do is cycle through the memory list, opening the record set using the strFilter to bring up a single record.  For instance:

for (int j=0; j<arsize; j++ ) {
      cRs.strFilter.Format("AcctIdx=%d", ar[j].nAcctIdx);
      cRs.Open(...
      // verify that the record was found, then...
      cRs.Edit(...
      cRs.Update()
      cRs.Close()
}

-- Dan
 

0
 

Author Comment

by:dooley090698
ID: 6860744
Dan,
I'm baffled!
I tried your suggestion (revised code here) but it still fails returning zero rows to update.
The update SQL statement has the field in it (m_bStatement) and after the Edit() the field is properly set.
It simply won't update the record set!
And why on only 2 of the data sets I have to play with!!
I can view these sets in Access and don't see any obvious problems and Access will happily modify the tables for me!
And no I can't simply use Access J
Do you have any other suggestions??
Sorry to be such a bother with this one but I really would like to know what's going on here!!

for (int a=0;a<arsize;a++)
          {
               // extract the struct from the array to view.
               tempStorage = AccountList.GetAt(a);
               // if the flag is set to print then set to true else false
               if( tempStorage.UseAct == true)
                    use = 1;
               else
                    use = 0;
               TRACE("Updating cust %s \n",tempStorage.ActName);

               CustAccounts.m_strFilter.Format("lId=%d", tempStorage.indx);

               if ( ! CustAccounts. IsOpen()  )
                    if (!CustAccounts.Open( AFX_DB_USE_DEFAULT_TYPE))
                    {
                         MessageBox(0,"Error","ERROR OPENING CUST DATA BASE",MB_OK);
                         return;
                    }
                   
                    // only change records if they need to be. Speeds up writing back to a huge data base
                    if (  CustAccounts.m_bStatement !=  use)
                    {
                         if (!CustAccounts.CanUpdate( ) )
                              AfxMessageBox("Cant Update " );
                         if ( CustAccounts.IsDeleted( ) )
                              AfxMessageBox("Deleted Record");
                         try{
                              CustAccounts.Edit();    
                         }
                         catch(CDBException * e)
                         {
                              CString errmsg = "Edit exception thrown :" + e->m_strError;
                              AfxMessageBox( errmsg,   MB_ICONSTOP    );
                              e->Delete();              
                         }
                         // set the recordset flag
                         CustAccounts.m_bStatement =  tempStorage.UseAct;
                         try{                    
                              if (! CustAccounts.Update() )
                                   AfxMessageBox("Update error");
                         }
                         catch(CDBException * e)
                         {
                              CString errmsg = "The exception thrown :" + e->m_strError;
                              AfxMessageBox( errmsg,   MB_ICONSTOP    );
                              e->Delete();              
                         }
                    }
                    // move to next record
                    CustAccounts.Close();
                    WinShow->Bar->SetPos(a);
          }
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6862228
I cleaned up your code and fixed some flaws.  The only way to test this is to SINGLE STEP THROUGH THE CODE which I was not able to do.

Also, why are you going through all the hassle of making a temporary 'use' value (I called it nUse).  Why not simply make the memory record field have the same value as the database field ( 0 or 1 )?

I also added code to catch non database errors.  I suspect that is one of the the problems.

-- Dan

// start with the recordset closed
if ( CustAccounts.IsOpen()  ) {
     CustAccounts.Close();
}

int nUse= 0;

for ( int a=0; a<arsize; a++ )  {
     tempStorage = AccountList.GetAt(a);

     nUse = 0;
     if( tempStorage.UseAct) nUse= 1;
     TRACE("Checking cust %s \n",tempStorage.ActName);

     CustAccounts.m_strFilter.Format("lId=%d", tempStorage.indx );

     if ( !CustAccounts.Open( AFX_DB_USE_DEFAULT_TYPE) ) {
          MessageBox(0,"Error","ERROR OPENING CUST RECORDSET",MB_OK);
          return;
     }
     //----------------------- please make sure you have more than 0 records
     //----------------------- 0 is less than 1 and 1 is an ideal number

     if ( CustAccounts.IsEOF() ) {
          MessageBox( "Oh No! oh NO!", "ooooops",  MB_ICONSTOP  ); // no such record
     }
     if ( CustAccounts.m_bStatement != nUse ) {
          TRACE("Updating cust %s \n",tempStorage.ActName);
          if (!CustAccounts.CanUpdate( ) ) AfxMessageBox("Cant Update " );
          if ( CustAccounts.IsDeleted( ) ) AfxMessageBox("Deleted Record");
          try{
               CustAccounts.Edit();    
          }
          catch( CDBException * e ) {
               CString errmsg= "Edit exception thrown :" + e->m_strError;
               AfxMessageBox( errmsg, MB_ICONSTOP );
               e->Delete();              
               return;
          }
          catch( CException* e )      {
               // Handle all other types of exceptions here.
               e->ReportError( MB_ICONSTOP );
          }

          // set the flag in the recordset
          CustAccounts.m_bStatement= nUse;
          try{                    
               if ( !CustAccounts.Update() ) {
                    AfxMessageBox("Update error");
               }
          }
          catch( CDBException * e ) {
               CString errmsg= "The exception thrown :" + e->m_strError;
               AfxMessageBox( errmsg,   MB_ICONSTOP );
               e->Delete();              
               return;
          }
          catch( CException* e )      {
               // Handle all other types of exceptions here.
               e->ReportError( MB_ICONSTOP );
          }
     }
     else {
          TRACE("No change needed for cust %s \n",tempStorage.ActName);
     }
     // move to next record
     CustAccounts.Close();
     WinShow->Bar->SetPos(a);
}
0
 

Author Comment

by:dooley090698
ID: 6864965
Dan,
Thanks for your assistance and for taking the time to check and modify my source! REALLY appreciated!

(BTW the only reason I used the Use variable was because my original structure contained a bool to print/not print and using the type BYTE Use variable was just a desperate attempt to see if incompatible variables (bool vs BYTE) might have been causing the problem.)

This is what I've found so far:
The program still fails at exactly the same spot with the SQLRowCount returning 0 causing the assert failure.
Now, if I add three records (accounts) through the originating software to the beginning of the table (ie AA Test1,AA Test2,AA Test3 ) the program cycles through THESE records as it should and updates the flag.
As soon as it comes to the first original record (ie Alpha Materials and Supplies) from the table it fails!
I've checked the security and it allows third party read/write operations so I'm not being locked out of the data set (and anyway, I can read the accounts, transactions etc in) and write to other tables.

I am at a total loss here and can't seem to isolate as to WHY the SQLRowCount  would return 0.

I feel I've taken up way too much of your time on this problem but if you have any other suggestions or approaches I could try I would certainly appreciate them.

If not, just let me know and I'll close this question and mark accordingly (excellent of course since you've been such a big help!)
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6865889
Have you checked the code that originally loads the data from the db into the memory array?  Make sure that it closes the recordset after it cycles through to collect the data.

>>I've checked the security and it allows third party read/write operations

Write a VERY SIMPLE tester routine.  It opens the database, then opens the recordset using an strFilter that will select exactly one of these 'problem' records.  Call Edit, then call Update, then call Close.

That will eliminate all other considerations and will verify that you have the ability to modify these records.

-- Dan
0
 

Author Comment

by:dooley090698
ID: 6868515
dan..
Oh wow..this is REALLY strange!!
I used your suggestion and wrote a simple little program to check the DB table.
I get the same failure (0 update) returned by the SQL statement mentioned earlier BUT.....
If I use the originating software (Simply in this case) and force it to rewrite the record (by modifying then saving) it process that record properly!
When I look at the data set in Access I can't see any reason why (ie no obvious character errors).
Ah well....don;t know what else to do!!
CRAP!!
Any other ideas
Txs
Colin
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6869452
In your test program, can you INSERT new records into that table?

Perhaps it is an NT/WIN2K security issue.  Maybe you don't have read+write permissions for the directory in which the database is stored.

If you use a user name and password when you open the database, then perhaps that user does not have the same access privileges as the "originating software" (whatever that is).  Can you examine user priviledges for the database?  

Is there any chance that some other program (the originaing software?) has locked the table?  MS Access may have a screen that shows which users have the db open and maybe even show what tables are locked.

One alternative to try:  Delete the orignal record then insert the modified one (rather than select and update).  It should not be necessary, but whatever works, works...

--=-=-=-=-=-=-==--=
I think you said you solved a similar problem with antother table by re-creating the table.  That might be your last resort.  But it shouldn't be that hard.  Just export the data to a CSV (text) file, create the table, and then import the data.

-- Dan

>>if we can get this sorted out it's gotta be worth a hell of a lot more than 100 points!!
>> PS..how can I get more points?? I've been stingy cause I'm running out!!

I'm pretty sure that you can buy question points (if not, I misunderstood my econ prof when she was talking about capitalism).  Check with Community Support or something.
0
 

Author Comment

by:dooley090698
ID: 6877165
Well Dan.How was your week end?
Mine sucked :)  Tried just about everything.
I can add records to the DB and they are pocessed just fine.(show up on table,can be modified etc.)
If I use the originating software to modify a  record that causes the assert error then that particular record works just fine.(can be modified,deleted)
If I try to delete a record causing the assert (no rows changed error) it returns a no rows effected by update/delete operation message.

These calls return assert errors (not too sure whether I can even use them..DESPERATION!!
testCust.Check(nRetCode );
testCust.GetRowStatus( wRow ) ;

I'm totaly stumped (as is Accpac apparantly..:) ) but I think they mis understood my question. Though it only related to records I wrote.

What to do???
Is it time to close off this quesiton and move on to another approach?
Txs for all you helap again!
Colin
0
 
LVL 49

Accepted Solution

by:
DanRollins earned 100 total points
ID: 6878086
>>Is it time to close off this quesiton ...

A question that describes the problem with your TEST
program (without any of the other complications) might be more visible and more easilty answered.

You never decribe the "originating software" and its nature might be relevant.  Is the "originating software" closed or open at the time you experience the error?

-- Dan
0
 

Author Comment

by:dooley090698
ID: 6878294
Dan,
I though I had mentioned that the originating program is Simply Accounting Ver 8.5.
And it's closed (it I try to open the data base I get a file sharing error anyway if the original application is running).
But thanks.
Rersent my request for assistance to ACCPAC tech support and explained in more detail what was going on.
And,if you can't help me..who on earth can :) :)
TXs Dan
I'll wait till tomotrrow and if the problems not resolved I'll close this question .

0
 

Author Comment

by:dooley090698
ID: 6879972
Excellent!!!    Excellent!!!    Excellent!!!    Excellent!!!    Excellent!!!
0
 

Author Comment

by:dooley090698
ID: 6879983
WOOHOOO!!!!
Dan.. I FOUND THE PROBLEM!!!! (at least I'm sue I have anyway!!)

There is a date/time signature stamp in the customer file that is updated whenever the record is modified in the originating software.
I found that by unbinding these 2 variables in the CRecordset class the program runs just fine on all data sets now.
What a process of elimination.. omg !!
The weird thing was that out of 6 data sets I have to work with, only 2 caused any grief, which is what was throwing me for a loop!
Had the program failed on all 6 data sets it would have made more sense,
Anyway, now I can forge ahead.
I'm checking with ACCPAC Tech Support about the need to update this field for what I am doing (changing the print flag only).
Just thought I'd throw this out to you in the off chance you run across something like this again,
Hmmm.. maybe I should become an EE Expert now cause I learned so much about DB programming from you in this go 'round with you ...lol
Thanks again for ALL your help (now and in the past)
PS I'm still using YOUR sort routine in my list boxes J



0
 

Author Comment

by:dooley090698
ID: 6879997
Another thing Dan..
Check your account for my points.. I upped the point value but it seems my account didn't go down by the point value (400).
Wanted to make sure you got them.
Also,wanted to award more but can't find a spot where I can buy more points (other than subscribing to the pro plan but only being a hobby programmer this is a lil beyond my means at present) and am afraid of running out!
Seems to me somewhere I read you could buy something like 1000 points for $20 or so....
Txs
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6881348
>>Check your account for my points..
I was awarded full credit for your 100-point question.  It does NOT cost you 400 points -- only 100 points.

I don't understand how modifying/not-modifying the datetime signature could affect your situation ... unless, perhaps you were placing an invalid value in one of those fields... but I would expect a different error in that case.

-- Dan
0
 

Author Comment

by:dooley090698
ID: 6882455
Dan,
I don't know either except I noticed that in the data field definitions supplied the time is stored as a BCD while the CRecordset has it stored as a CTime object.
Is there any difference??
As I said,since the program worked just fine on 4 of the six sets I was assuming the error was in the data sets not in the code.
I'm going to run it as is on a few more sets just to make sure.
0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

Introduction: Dynamic window placements and drawing on a form, simple usage of windows registry as a storage place for information. Continuing from the first article about sudoku.  There we have designed the application and put a lot of user int…
Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now