Get validation using database object

Get validation using database object

Postby wpacheco » Fri Jan 06, 2006 4:28 pm

I'm working with a database object and need to validate a get assigned to one field of the database object. Example:
Code: Select all  Expand view
redefine get oGet[ 1] var oNomTra:nomtracod id 1001 of oFld:aDialogs[1] picture '@!' update
...
...
oNomTra:Blank()
...
...
nReg := oNomTra:RecNo()
oNomTra:Seek( oNomTra:nomtracod )
oNomTra:GoTo(nReg)

The question is I've noticed that if I make the search for validation propossal with this code I lost the initial value of the gets it takes the database record value. I try to assign the get's initial value to a var in order to perform the validation like this
Code: Select all  Expand view
cCode := oNomTra:nomtracod
oNomTra:lBuffer := .f.
oNomTra:Seek( cCode )
oNomTra:GoTo(nReg)
oNomTra:lBuffer := .t.

but after set the buffer of the database object to false the var value is lost.
So, I need to make a validation keeping the original values of the gets

Thanks for your comments
User avatar
wpacheco
 
Posts: 28
Joined: Tue Nov 15, 2005 1:03 am
Location: Isla Margarita, Venezuela

Postby James Bott » Fri Jan 06, 2006 4:49 pm

It looks like you are calling the blank() method before the seek. This will refill the buffer with blank data--all the fields will be blank. I am not clear why you are calling blank()?

If you don't call blank(), turning lBuffer off, then on, should work. If it still doesn't then we need to see more of your code.

James
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Postby reinaldocrespo » Fri Jan 06, 2006 5:00 pm

William;

redefine get oget[ 1 ] var oNomTra:VarNomTracod id ... ;
Valid (is_valid( onomTra:VarNomTraCod .... ) )

Where oNomTra:VarNomTraCod is the buffer where data is being input, Is_valid(...) is a function that recieves the inputed value and returns .t. if acceptable and .f. if not which you may later .or./.and. with a MsgYesNo stating the fact.

If clicking on Save button, then oNomTra:Save() is called which will actually lock the record and save the buffer data to the database.

Hope this helps.

If you want a generic is_valid fuction that validates info against a db, I'll post it.

Reinaldo Crespo.
User avatar
reinaldocrespo
 
Posts: 979
Joined: Thu Nov 17, 2005 5:49 pm
Location: Fort Lauderdale, FL

Postby wpacheco » Fri Jan 06, 2006 9:47 pm

Ok. thanks guys... Let me explain better

My prog in first instance define some gets linked to a database object.
Code: Select all  Expand view
redefine get oGet[ 1] var oNomTra:nomtracod id 1001 of oDlg picture '@!' update

After that, there is a button I use to edit the get's trought a function.
Code: Select all  Expand view
redefine sbutton oBtn[1] id 1111 of oDlg name "New" nobox update ;
         caption "New" text 3 tooltip "New record" ;
         action ( NonTraEdit( "NEW", oNomTra, oBtn, oGet, oRadio, oLbx[1], oImg, oWChild) )

In the function there exist the Blank() method to allow the get edition and one routine to validate the user input
Code: Select all  Expand view
function NonTraEdit( cModo, oNomTra, oBtn, oGet, oRadio, oLbx, oImg, oWChild )
   do case
   case cModo $ "NEW,EDIT"
      lNew := ( cModo = "NEW" )
      if lNew
         oNomTra:Blank()
      else
         if ! oNomTra:RecLock()
            lGo := .f.
         endif
      endif

      if lGo
      ...

The same function is called by another button to validate the gets
Code: Select all  Expand view
   case cModo = "CHECK"
      do case
      case Empty( oNomTra:nomtracod )
         MsgStop( "The code can't be empty", "Error" )
         oGet[1]:SetFocus()
         lGo := .f.
      case ...
      case ...
      endcase
      ...
      ...
      nReg := oNomTra:RecNo()
      oNomTra:lBuffer := .f.
      oNomTra:Seek( oNomTra:nomtracod )
      if oNomTra:Found()
          ...
          lGo := .f.
      endif
      oNomTra:GoTo(nReg)
      oNomTra:lBuffer := .t.

There is where the problem exist. The get initially has the user input value. I want to check if the code there exist in the database file. So, I do a search with the get value, but because the TDatabase Seek() method has a load() method inside makes the original get's value change.
If I try to set to false the object database buffer, this causes that the values are lost.
If I do the search without set the database buffer to false then all get takes the value of the database record. So of any way always I lose the original values
User avatar
wpacheco
 
Posts: 28
Joined: Tue Nov 15, 2005 1:03 am
Location: Isla Margarita, Venezuela

Postby James Bott » Sat Jan 07, 2006 2:21 am

Well, I still think it should work. I don't see a problem in your code so the problem must be in code we haven't seen yet.

However, I do think you are making your life more difficult that it need be. First, I suggest going to my website and reading the artciles about building database objects.

http://ourworld.compuserve.com/homepage ... rogram.htm

I will try to summarize them here.

Make a subclass of TDatabase that contains methods add() and edit(). This makes your code much easier and also allows you to use polymorphism later. In this case you are also going to need an isUnique() method (although I wonder why you don't just generate a unique ID automatically).

Code: Select all  Expand view
class TCustomer from TDatabase
   data lAdd hidden
   method add
   method edit
   method isUnique
end

method add()
   lAdd:=.t.
   ::edit()
   lAdd:=.f.
   ::load()
return self

method edit()
   local oDlg
   if ::lAdd
      ::blank()
   endif
   define dialog oDlg
   ...
   redefine get oGet ::nomtracod valid isUnique( oGet:varGet() )
   redefine button ID_OK action ::save()
   activate dialog oDlg
return self

method isUnique(cNomtracod)
   local nRecno:=::recno()
   local lSuccess:=.f.
   ::lBuffer:=.f.
   ::seek(cNomtracod)
   if ::found()
      msgInfo(...)
   else
      ::lSuccess:=.t.
   endif
   ::goto(::nRecno)
   ::lBuffer:=.t.
return lSuccess


That is the basics of it. Now you can do:

oCustomer:edit()

or,

oCustomer:add()

If you are trying to get the user to input a unique primary-key value, then I would not. For the user this is a real pain--it's like typing into a black hole. They don't know what to type and there is nothing to help them but a rude error message. I would generate sequential keys automatically.

If you are trying to get the user to type in a valid pre-existing code, then I would use a combobox instead. Better, with DBCombo, you can provide a list of descriptions and automatically get the corresponding code. This way the user doesn't even have to know the codes. The lastest version of DBCombo also has a dynamic search so the user can type in a few keystrokes to get the first match.

Perhaps something in here helps...

Regards,
James
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Postby wpacheco » Sat Jan 07, 2006 3:54 pm

Thanks James

I think you're right but there are some events I'm considering for a technique of effective validation like pre and post validation necessary in a real multiuser environment.

TDatabase class at the moment does not offers methods to implement it. This is the reason for which I chose to post validate just at the saving time. I thought to use an inherited method of TDatabase class that does not make use of Load() when it makes the search, this way I can maintain the original values of get with no need to change the buffer data.

Of all ways thank you very much by your collaboration and time
User avatar
wpacheco
 
Posts: 28
Joined: Tue Nov 15, 2005 1:03 am
Location: Isla Margarita, Venezuela


Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: No registered users and 55 guests