Chris Miller
Programmer
Since we had a discussion about this and Mike Lewis Hexcentral article about SCOPE_IDENTITY() not working, I thought about a general way.
The solution is using REFRESH() instead of REQUERY(). There's just a bummer in the description of REFRESH(): You already have to know the PK to use it to refresh your view records, and that's the very thing we don't know and want to refresh, so this seems like a deed end.
I already proposed the idea to add a column for storing something specific to your process so you can re-identify your own (new) records. To bring these two things together, REFRESH() could solve the refresh of the id if the additional column could be the PK temporarily, ie during the INSERT. And I was astonished: It's possible to change KeyFieldList of the view workarea.
So these are the ingredients:
[ol 1]
[li]Define your remote view as usual with the PK column and updatable columns. In the SQL you'll find something like
[/li]
[li]Add a tempid column to the table (maybe uniqueidentifier or an int, but no identity, no default value) and make that a sparse column.[/li]
[li]In the view definition, this needs to be added as a normal updatable column, not a KeyField, yet it will be temporally used for KeyFieldList.
[/li]
[li]Think of what to store in tempid, either you generate GUIDs or maybe use a sequence in the database. When you add records you set this column uniquely in your application in the view.
[/li][/ol]
Now to commmit your new view records with tempids set keyfieldlist to 'tempid' (by CURSORSETPROP, not by DBSETPROP). After the TABLEUPDATE you do a REFRESH which also uses tempid as the PK. Then set keyfieldlist back to the normal PK 'id'. To tidy up the database replace all current tempids with NULL in the view and commit that with another TABLEUPDATE. As tempid is sparse, NULLs are effectively not stored in comparison to a normal nullable column, so this will only slightly increase the database size, even if you introduce this to all your backend tables.
I don't recommend using tempid instead of id to simply make this a replacement for IDENTITY. Other database administration and maintenance and other client applications, which are not using tempid are still better served with a server-side generated key. Not making use of tempid it'll be NULL and that's fine.
Chriss
The solution is using REFRESH() instead of REQUERY(). There's just a bummer in the description of REFRESH(): You already have to know the PK to use it to refresh your view records, and that's the very thing we don't know and want to refresh, so this seems like a deed end.
I already proposed the idea to add a column for storing something specific to your process so you can re-identify your own (new) records. To bring these two things together, REFRESH() could solve the refresh of the id if the additional column could be the PK temporarily, ie during the INSERT. And I was astonished: It's possible to change KeyFieldList of the view workarea.
So these are the ingredients:
[ol 1]
[li]Define your remote view as usual with the PK column and updatable columns. In the SQL you'll find something like
Code:
DBSetProp(ThisView+".id","Field","KeyField",.T.)
[li]Add a tempid column to the table (maybe uniqueidentifier or an int, but no identity, no default value) and make that a sparse column.[/li]
[li]In the view definition, this needs to be added as a normal updatable column, not a KeyField, yet it will be temporally used for KeyFieldList.
[/li]
[li]Think of what to store in tempid, either you generate GUIDs or maybe use a sequence in the database. When you add records you set this column uniquely in your application in the view.
[/li][/ol]
Now to commmit your new view records with tempids set keyfieldlist to 'tempid' (by CURSORSETPROP, not by DBSETPROP). After the TABLEUPDATE you do a REFRESH which also uses tempid as the PK. Then set keyfieldlist back to the normal PK 'id'. To tidy up the database replace all current tempids with NULL in the view and commit that with another TABLEUPDATE. As tempid is sparse, NULLs are effectively not stored in comparison to a normal nullable column, so this will only slightly increase the database size, even if you introduce this to all your backend tables.
I don't recommend using tempid instead of id to simply make this a replacement for IDENTITY. Other database administration and maintenance and other client applications, which are not using tempid are still better served with a server-side generated key. Not making use of tempid it'll be NULL and that's fine.
Chriss