Subject Re: AW: [IBO] Dataset was not found to be deleted
Author Helen Borrie
At 03:52 PM 29/01/2004 +0100, you wrote:
>Hello Helen,
>
>thank you for your hints.
> >
>You have missing or wrong KeyLinks in your dataset object (TIB_Query, etc.)
><
>I am using the query editor (dbl click on the query component) to generate
>the Edit-/Insert-/Update - SQL and I noticed that "generate for table"
>made a :
>
>DELETE FROM <my table>
>WHERE
>RDB$DB_KEY = :DB_KEY
>
>When I replace the
>
>RDB$DB_KEY = :DB_KEY
>
>with
>
>PS_ID = :PS_ID
>
>which is a UNIQUE ASCENDING INDEX on this table then every thing works fine.
>What is the background of RDB$DB_KEY here?

You don't have a primary key on this table, right? Then use PS_ID as your
KeyLinks. Now, if this is a nullable field (which is allowed for unique
indexes in Fb 1.5) you must enforce it in your application explicitly,
because your metadata won't help--that means setting its REQUIRED attribute
true.

OTOH, if the dataset has joins, PS_ID won't be enough and you don't have an
updatable dataset anyway. You have to do more to get a unique set of
keylinks and you need either KEYRELATION (to update only one of the base
tables) or custom xxxxSQL properties that call executable parameterised
statements supplied by you.

The rdb$db_key is a special value that the database returns with sets that
have no key. It's unique within the combined context of the set and the
transaction but it survives only as long as the transaction, and it can't
be used for finding the db row for a positioned update if there's a join.

And of course, it becomes outdated as soon as anything committed, hence the
"lost position" that causes your error.


> >>Where do I have to put my try/Except to catch this exception?
> >
> >This isn't the kind of error that you could catch and throw back to the
> >user - it's a programmer error.
>
>You are definitely right her, but the reason I asked this question is:
>I have a similar problem on two other tables. One holds current process
>data and the other is a process data archive. When a dataset gets "done"
>it is copied to the archive.

Without keylinks or enforcement by the metadata rules, you are "flying
blind" wrt positioned updates.

>I have a KeySource-Lookoup relation on the process data using a
>IB_LookupCombo dropped on the grid.
>If the user now selects the field to modify the lookup combo comes up
>giving him choice from a other table. If now the corresponding dataset

row?

> gets copied to the archive before the user made his choice

How does this happen? An embedded lookup only works during edit mode. I
fail to understand how the app could post anything while the lookup
operation was incomplete.

>I get the Exception that "the datarow is not found to be updated". Now I
>could use the catch exception here and by code update the right dataset in
>the archieve.

With no metadata rules to help, you need to use the BeforePost event in any
case, to enforce the logical positioning requirements, i.e. keys, and avoid
getting this exception back when the Post event fails to update a row.

>So I still would like to know : Where do I have to put my try/Except to
>catch this exception?

There is no database exception, since the UpdateSQL statement merely does
nothing if it can't locate a row specified in an update request. However,
the dataset expects RowsAffected to be 1 after the Post. If it comes back
as 0, the dataset throws its own exception - the one you are seeing. You
can test the exception message for E_RECORD_NOT_LOCATED_FOR_UPDATE in
AfterPost.

But it still really gets back to designing the app so that an update always
finds the row. And that gets back to correct KeyLinks.

Helen