Page 1 of 1

oRs:EditBaseRecord, oRec:Save() problem

Posted: Thu Aug 23, 2018 7:13 am
by betoncu
I have explained the problem step by step as below:

Please, run the mariainv example of Mr. Rao

1. Open items and position the cursor on an item
2. Press the edit button and open the edit dialog
3. Now, when we are waiting here, another user has deleted the record that we are editing.
4. Edit the record. (Modify the name of the item)
5. Press Save button
6. Of course nothing happens.
7. Press the Save button again
8. oRec:Save() modified another record, since the pointer positioned on that record.

How can I overcome this problem. oRec:Save() returns false
but there is no any sql error. What can we do?

Re: oRs:EditBaseRecord, oRec:Save() problem

Posted: Fri Aug 24, 2018 7:23 am
by nageswaragunupudi
We are looking into this.

Re: oRs:EditBaseRecord, oRec:Save() problem

Posted: Sat Aug 25, 2018 3:47 pm
by nageswaragunupudi
Can you please make this modification in \fwh\source\classes\datarow.prg and test?

Please locate the following lines towards the end of method SaveOBJ()

Code: Select all | Expand

     if !lSaved
         AEval( ::aData, { |a,i| a[ 2 ] := aSave[ i ] } )
      endif
 

Please comment out this line like this:

Code: Select all | Expand

     if !lSaved
//         AEval( ::aData, { |a,i| a[ 2 ] := aSave[ i ] } )
      endif
 


Can you please test after this change and provide your comments?

Re: oRs:EditBaseRecord, oRec:Save() problem

Posted: Sun Aug 26, 2018 2:28 pm
by betoncu
Dear Rao,

The problem described in the link below came back
viewtopic.php?f=3&t=33908&start=15#p201244

Re: oRs:EditBaseRecord, oRec:Save() problem

Posted: Sun Aug 26, 2018 4:35 pm
by nageswaragunupudi
Thanks for the feedback.

Now, please change the entire method SaveOBJ() in datarow.prg with this new method.

Code: Select all | Expand

METHOD SaveOBJ() CLASS TDataRow

   local lSaved      := .t.
   local lNetChanged := .f.
   local aSaveData   := {}

   if ::lReadOnly .or. ! ::Modified()
      return .f.
   endif

   if __ObjHasMethod( ::uSource, "ROWPUT" )

      aSaveData   := AClone( ::aData )

      ::RecNo     := ::uSource:RowPut( ::aData, ::RecNo, .f., Self, @lSaved )
      if ValType( lSaved ) != 'L'
         lSaved   := .t.
      endif
      if lSaved
         ::aOrg      := AClone( ::aData )
      else
         AEval( ::aData, { |a,i| If( a[ 2 ] == ::aOrg[ i, 2 ], nil, lNetChanged := .t. ) } )
         ::aOrg      := AClone( ::aData )
         if !lNetChanged
            AEval( ::aData, { |a,i| a[ 2 ] := aSaveData[ i, 2 ] } )
         endif
      endif
   endif

return lSaved
 

Can you please provide your comments after making this change?

Re: oRs:EditBaseRecord, oRec:Save() problem

Posted: Sun Aug 26, 2018 9:40 pm
by betoncu
The record pointer goes to the first record and changes all of the fields of oRec with the values of first record and I loose everything that I have typed.

Re: oRs:EditBaseRecord, oRec:Save() problem

Posted: Sun Aug 26, 2018 9:46 pm
by nageswaragunupudi
This is what is happening in my tests:

If the save fails due to some reason like duplicated unique field, the record pointer does not change and edited values are not lost. They are retained.

If the save fails because the record is deleted by another user on the network, then the record pointer is moved to the next record and changes made by the user are lost, as it should be.

Can you explain what is happening in your case, step by step?

Re: oRs:EditBaseRecord, oRec:Save() problem

Posted: Sun Aug 26, 2018 10:01 pm
by betoncu
Mr. Rao, since the oRec:Save() returns false the execution waits in the edit dialog.
In this case there is nothing to do in the edit dialog.
Instead of waiting in the edit dialog, may be we have to show an error message that says record has been deleted by another user and go back to browse.

Re: oRs:EditBaseRecord, oRec:Save() problem

Posted: Sun Aug 26, 2018 10:20 pm
by betoncu
I have made the following change in the EditItems function.
Instead of using oRec:Save() directly, I have add another function ItemSaved() and Ithink the problem solved.
I have used the original datarow.prg.
Of course some more lines like oRsItems:ReSync(), oBrw:RefreshCurrent() is needed.

Code: Select all | Expand

static function EditItems( oRec )
 ...
    // ACTION If( oRec:Save(), oDlg:End(), nil )
   ACTION If( ItemSaved(oRec), oDlg:End(), nil )
...
return nil

//----------------------------------------------------------------------------//

static function ItemSaved(oRec)
   local lNotSavedButNoError := .F.
   local lSaved              := .F.

   BEGIN SEQUENCE
      oCn:Execute( "BEGIN" )
      IF !oRec:Save()
         IF oCn:nError = 0  //There is no Sql error. May be the item deleted by another user ???
            lNotSavedButNoError := .T.
         ENDIF
         BREAK
      ENDIF
      oCn:Execute( "COMMIT" )
      lSaved := .T.
   RECOVER
      oCn:Execute( "ROLLBACK" )
   END SEQUENCE

   lSaved := lSaved .OR. lNotSavedButNoError

return lSaved