Page 1 of 1

Tdatabase Question

Posted: Sat Dec 10, 2005 12:13 am
by Jeff Barnes
HI,

I have tried for the first time tDatabase ... wow have I been doing a lot mode code then I had to :-(

Anyway...

I open my database like this:

Use myfile.dbf shared new
DATABASE oMyfile

As a test I open a dialog with some gets and test SAVE and CANCEL.
oMyFile:Load()
Redefine Get.... oMyfile:Field1 etc....

If the user selects SAVE I issue a oMyfile:Save()

So far it works they way I expect.


Now I ran my program twice (2 copies at the same time) and something strange happens.


If I make different changes in the 2 separate programs:
example in App1 I change field1 and in App2 I change field2.

Now I issue a SAVE() and reload the dbf data oMyfile:Load()

App1 shows the changes I made in App1 and App2 shows the changes I made in App2.

I would think that one of the Apps would give a lock error and after the LOAD() command both Apps would be the same.

Any idea why this would happen?

Thanks,
Jeff

Posted: Sat Dec 10, 2005 8:17 am
by Antonio Linares
Jeff,

Class TDataBase properly manages locks, but just when saving the data.

The problem is that it uses a buffer (an array), so when you are going to save it to the real DBF file, the values may have changed in the DBF file, and the buffer may have old ones.

You may check the buffer values against the DBF file data before saving to see if some values have changed, ot change the lock style in Class TDataBase, to lock the DBF record meanwhile you are editing, not only meanwhile you are saving.

Posted: Sat Dec 10, 2005 10:38 pm
by James Bott
Jeff,

As Antonio mentioned, TDatabase uses opitmistic locking. If you want to change this to pessimistic locking, you can modify the load() method to lock the record and the save method to unlock. You will also have to remember to unlock on cancel and you need to keep in mind that if the user just wants to look at the data, the record is going to get locked.

I highly recommend that you subclass the database class and use it in your program rather than calling TDatabase directly. This way if you decide to change the behavior of the database class you can do it in the subclass and it will be used throughout your application. Just start with this:

Code: Select all

class TXData from TDatabase
endclass
That is all you need. Then use the TXData class instead of TDatabase. Should you decide to change the load method you can just add it to TXData.

Code: Select all

class TXData from TDatabase
   method load
endclass

method load()
   ::reclock()
return super:load()
I have oversimplifed this a little--you will have to handle a lock failure if it is already locked.

I have been using optimistic locking for many years without any problems.

You may also want to read the articles I wrote on using database classes. They are available here:

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


James