Icon View Thread

The following is the text of the current message along with any replies.
Messages 1 to 10 of 11 total
Thread Confused: Error 8708 Record has been changed or deleted by another user
Tue, Feb 27 2007 4:33 PMPermanent Link

Sam Davis
I'm getting this error message and I know why, but ...

Here's what's happening. My Delphi app is running and has gone and added
10 rows to a table. After the loop has completed, I go over to DSU and
delete the 10 rows because I want to rerun the test. I rerun the test
(my program hasn't closed) and my routine instantiates a TDBISAMTable
and connects to the database. This table then does a FindKey and it
finds the deleted record!? Why? The record is gone. Since it finds the
record it then tries to put it into Edit mode and that's when I get the
error "#8708-Record has been changed or deleted by another users...".

So why doesn't TDBISAMTable know that the rows in the table have been
deleted? What am I doing wrong? I currently have StrictChangeDetection
set to False (default).

TIA

Sam
Tue, Feb 27 2007 8:02 PMPermanent Link

Jose Eduardo Helminsky
Sam

It is a matter of buffers thing.

Your application instantiate one TDBISamTable. The DBSys instantiate other (of course) and when you delete the
records, the instance created inside your application doesn´t know if they were deleted. You need to apply a
Refresh method inside your application just before you want to rerun the tests.

Another thing you can do is set StrictChangeDetection to True and DBISAM always check if the buffers were
changed (updated or deleted) and you don´t need to apply a Refresh. But I do not recomend it, it works like
expected but it will slow down a lot your application.

Eduardo
Tue, Feb 27 2007 11:15 PMPermanent Link

Sam Davis
Jose Eduardo Helminsky wrote:

> Sam
>
> It is a matter of buffers thing.
>
> Your application instantiate one TDBISamTable. The DBSys instantiate other (of course) and when you delete the
> records, the instance created inside your application doesn´t know if they were deleted. You need to apply a
> Refresh method inside your application just before you want to rerun the tests.

My application instantiated the TDBISAMTable *after* the rows were
deleted. So I would have assumed it did a Refresh when the table was
opened which meant it should have the buffers without the deleted rows.

>
> Another thing you can do is set StrictChangeDetection to True and DBISAM always check if the buffers were
> changed (updated or deleted) and you don´t need to apply a Refresh. But I do not recomend it, it works like
> expected but it will slow down a lot your application.

But isn't that how multiuser databases are suppose to work? If someone
deletes rows from a table, shouldn't the other applications be aware of
it? Otherwise they are dealing with buffers that have records that no
longer exist and isn't that going to create a whole mess of problems
that the developer has to program around because he has to handle
phantom records? I don't recall any other 3rd party database doing this,
or am I mistaken?

TIA

Sam
Wed, Feb 28 2007 3:27 AMPermanent Link

Roy Lambert

NLH Associates

Team Elevate Team Elevate

Sam


>My application instantiated the TDBISAMTable *after* the rows were
>deleted. So I would have assumed it did a Refresh when the table was
>opened which meant it should have the buffers without the deleted rows.

If by instantiated you mean you destroyed the table and then created a new instance then yes it should have been refreshed. If your app really had closed the table and then re-opened it it should have been refreshed. Check wether it was ever closed in the first place.
>
>>
>> Another thing you can do is set StrictChangeDetection to True and DBISAM always check if the buffers were
>> changed (updated or deleted) and you don´t need to apply a Refresh. But I do not recomend it, it works like
>> expected but it will slow down a lot your application.
>
>But isn't that how multiuser databases are suppose to work? If someone
>deletes rows from a table, shouldn't the other applications be aware of
>it? Otherwise they are dealing with buffers that have records that no
>longer exist and isn't that going to create a whole mess of problems
>that the developer has to program around because he has to handle
>phantom records? I don't recall any other 3rd party database doing this,
>or am I mistaken?

Yes and no. The only way to do it fully is to check for changes before each and every action on the database. There's a lot of overhead associated with this. Its easier in c/s setups than local fileserver since the engine can set flags for operations (or however its done) in a fileserver environment its much more difficult.

Then you get to big metal stuff and sql where you might be working with canned datasets which know nothing about the database.

Roy Lambert
Wed, Feb 28 2007 8:18 AMPermanent Link

"Robert"

"Sam Davis" <sammyd432@yahoo.com> wrote in message
news:D6B0BF4A-41E1-4C11-AEC6-352A6A650A40@news.elevatesoft.com...
>
> So why doesn't TDBISAMTable know that the rows in the table have been
> deleted? What am I doing wrong? I currently have StrictChangeDetection set
> to False (default).
>

It is possible that you have the table open in your application. DBISAM acts
differently on "multi user" if the table is opened twice in the same
program, or if it is open by separate programs (whether that should be the
case, I don't know).

See project multi.zip in binaries. If you change a row in one grid and then
try to change it in the other, you immediately get an 8708, even though the
lock protocol is set to optimistic. However, if you load two copies of the
program, you can go ahead and edit the record, and you'll only get the 8708
when you try to post (as expected).

I think it has something to do with DBISAM only opening the dataset once,
maybe Tim can give us some more details. Anyway, you need to be careful when
opening a table multiple times in the same program, you don't get a fresh
copy of the disk table.

Do the following test on the multi project:

1. Start a copy of the program. Close the lower table (press the button)
2. Start another copy of the program. Change one of the rows.
3. Go back to the first program, open the second table (press button again),
and you'll see that it still displays the old values.

Robert

Wed, Feb 28 2007 9:05 AMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Sam,

<< My application instantiated the TDBISAMTable *after* the rows were
deleted. So I would have assumed it did a Refresh when the table was opened
which meant it should have the buffers without the deleted rows. >>

DBISAM won't do an automatic refresh when you open a table if the table is
already opened elsewhere in the application.  It does this for purposes of
performance and maintaining coherency in what data is available to all of
the table cursors in the application.

--
Tim Young
Elevate Software
www.elevatesoft.com

Wed, Feb 28 2007 10:54 AMPermanent Link

Sam Davis
Tim Young [Elevate Software] wrote:

> Sam,
>
> << My application instantiated the TDBISAMTable *after* the rows were
> deleted. So I would have assumed it did a Refresh when the table was opened
> which meant it should have the buffers without the deleted rows. >>
>
> DBISAM won't do an automatic refresh when you open a table if the table is
> already opened elsewhere in the application.  It does this for purposes of
> performance and maintaining coherency in what data is available to all of
> the table cursors in the application.
>

Yes, there was another copy of the table already opened when the second
table was instantiated. So I guess they share the same buffers. I had
incorrectly assumed when the table was opened it would fetch the rows
from disk, not from the internal buffer.

So if there are a lot of updates going on between users (POS for
example), the tables in each application won't see the other's changes
unless the table is refreshed. So if the program is running for a day,
hundreds of changes could have been done to the table by the other user
like decrementing inventory, updating invoices, etc. that the other user
won't see until the table is refreshed. So what happens if user#1 opens
a table at 9:00AM and user#2 at 9:10AM changes record#2. User#1 edits
record#2 at 4:00PM (program has been running all day).

1) Is user#1 allowed to edit record#2,
2) or will he get an error saying it was modified by someone else?
3) of if he can edit record#2, will the values be current?

From what you've told me, I suspect the answer is 2. In which case most
of the records may have been changed by someone else over the course of
the day.

Same thing with inventory. If user#2 is filling orders and decrementing
inventory, then user#1 won't see these changes unless
StrictChangeDetection is set to True. Correct? If so, then I don't see
any way of having StrictChangeDetection set to False in a multi-user
environment where updates are occurring. Is that correct?

TIA

Sam
Wed, Feb 28 2007 11:20 AMPermanent Link

Roy Lambert

NLH Associates

Team Elevate Team Elevate

Sam


>1) Is user#1 allowed to edit record#2,
>2) or will he get an error saying it was modified by someone else?
>3) of if he can edit record#2, will the values be current?
>
> From what you've told me, I suspect the answer is 2.

Correct

>In which case most
>of the records may have been changed by someone else over the course of
>the day.

Nah that'll happen regardless Smiley

>Same thing with inventory. If user#2 is filling orders and decrementing
>inventory, then user#1 won't see these changes unless
>StrictChangeDetection is set to True. Correct? If so, then I don't see
>any way of having StrictChangeDetection set to False in a multi-user
>environment where updates are occurring. Is that correct?

If you want to have a grid sitting on the screen and have it constantly change as users at other stations make changes nothing will help apart from a periodic refresh. If you want to allow users to edit after the data has been changed all you need is an 8708 eater. There's a good one in the manual. If you don't like it post again and I'll send you mine.

Roy Lambert
Wed, Feb 28 2007 11:27 AMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Sam,

<<1) Is user#1 allowed to edit record#2,
2) or will he get an error saying it was modified by someone else?
3) of if he can edit record#2, will the values be current?

From what you've told me, I suspect the answer is 2. >>

Correct.

<< Same thing with inventory. If user#2 is filling orders and decrementing
inventory, then user#1 won't see these changes unless StrictChangeDetection
is set to True. Correct? If so, then I don't see any way of having
StrictChangeDetection set to False in a multi-user environment where updates
are occurring. Is that correct? >>

Updates always use the most current version of any given row:

http://www.elevatesoft.com/dbisam4d5_change_detection.htm

--
Tim Young
Elevate Software
www.elevatesoft.com

Wed, Feb 28 2007 11:39 AMPermanent Link

"Robert"

"Sam Davis" <sammyd432@yahoo.com> wrote in message
news:0B0744B8-321E-4662-A763-DB7056A420FC@news.elevatesoft.com...
>
> So if there are a lot of updates going on between users (POS for example),
> the tables in each application won't see the other's changes unless the
> table is refreshed.

Correct. Keep in mind that a table is also refreshed when you scroll thru a
dbgrid.

So if the program is running for a day,
> hundreds of changes could have been done to the table by the other user
> like decrementing inventory, updating invoices, etc. that the other user
> won't see until the table is refreshed. So what happens if user#1 opens a
> table at 9:00AM and user#2 at 9:10AM changes record#2. User#1 edits
> record#2 at 4:00PM (program has been running all day).
>
> 1) Is user#1 allowed to edit record#2,
> 2) or will he get an error saying it was modified by someone else?
> 3) of if he can edit record#2, will the values be current?
>

Depends on the lock option. Pessimistic, you will get the 8708 as soon as
you edit the record. Optimistic, you get the error when you attempt to post.
In either case, the values are not current until you refresh the record.

> From what you've told me, I suspect the answer is 2. In which case most of
> the records may have been changed by someone else over the course of the
> day.
>
> Same thing with inventory. If user#2 is filling orders and decrementing
> inventory, then user#1 won't see these changes unless
> StrictChangeDetection is set to True. Correct? If so, then I don't see any
> way of having StrictChangeDetection set to False in a multi-user
> environment where updates are occurring. Is that correct?
>

StrictChangeDetection is a very poor solution, IMO. But then again, it all
depends on the application. Read the change detection section in the DBISAM
manual, it is very good as is all the rest of the concurrency documentation.

Also keep in mind that if you want to do an update to a row without
consideration of previous values (for example, when increasing or decreasing
inventory), you can use SQL. That way, you don't have to worry about an
8708.

Robert


Page 1 of 2Next Page »
Jump to Page:  1 2
Image