Hi, Using Delphi client and C# Server, using strongly types datasets in Delphi.
When we put a record in insert and show an edit form, then type in something existing against a a field set up as unique. We Post then applyupdates(F,T) - on exception it moves to the 1st record. We want to cancel the post - but stay on the record being inserted. How do we do this?
Also where is it the best place to trap these type of exceptions?.. FK’s/Uniques etc and supply the exception message - we do not want to use the ShowReconcile, but just handle the exception for our users.
Good question, I did a similar one and they simply mentioned logged as #xxxx. I was expecting that the duplicate keys, indexes, etc will be detected on the client side without having to applyupdates and that there will be a way (an event like in the TClientDataSet) that we can use to manage the error with no reconciliation dialog.
It is a fairly common situation so I’m a bit confused on why it is not there. Anyone on RO with more comments on it?
We want to cancel the post - but stay on the record being inserted. How do we do this?
Please use TDAMemDataTable.CancelUpdates methos to cancel changes.
on exception it moves to the 1st record.
Can you send us a small testcase which reproduces this behavior?
Also where is it the best place to trap these type of exceptions?
The simple way is using reconcile events for this purpose, but don’t show reconcile dialog. Change error message
for users in TDARemoteDataAdapter.OnGenerateRecordMessage event.
I have created a sample project, set up as the same as ours - it reproduces the issue of setting up a master detail relationship - inserting a details record on a table that a has a unique index - capturing the message as you described and cancelling the changes makes it go to the first detail record… which is the issue.
But I found if I unhook master detail and manually set the Id of the master onto the detail record at insert then the edit fails but stays on the data i entered… which is correct.
I have attached a client in Delphi, a Server in C# VS2010, a Database scripts - all you have to do is setup you database username/password in the connections in VS for the database. We are using the latest RO for both Delphi and VS. See attached.
Thanks thought it was a bug! What is the ETA for this as this is a very urgent fix for us.
Now for me to get around unique key constraints I guess I have to resort to firing off a SQL ‘‘íf exists’’ prior to a post/apply-updates… is this best way to go about it?
procedure TDADataTable.MergeDelta;
var
.....................
bm: TBookmark;
.....................
// Disables the M/D relationship so that Locates can work in all cases (master or detail tables, regardless
// of their positioning)
//if not (ruoOnPost in oldopt) then MasterSource := NIL;
if not (ruoOnPost in oldopt) then begin
MasterSource := NIL;
bm := GetBookmark;
end;
......................
// Restores the M/D relationship
//if not (ruoOnPost in oldopt) then MasterSource := oldmastersource;
if not (ruoOnPost in oldopt) then begin
MasterSource := oldmastersource;
if BookmarkValid(bm) then GotoBookmark(bm);
end;
Thanks, I have to test further but at the moment it is not working all the time. Not sure if this is due to Grid sorts etc. BUT if I have a valid bookmark why is this code firing - it is in the middle of the two blocks you provided above - if bookmark is valid - why go to first and then locate??? - is this now redundant in some form?
// Locates the original record
First;
if not Locate(pkfields, keyvals, []) then begin
if Assigned(fOnMergeDeltaUnknownChange) then fOnMergeDeltaUnknownChange(Self, fDelta,Delta[i]);
Continue;
end;
I Will provide more feedback once I Have worked through any grid issues - but at the moment it is NOT fully functional - ie some times it goes to the new record, sometimes it doesn’t - 50/50.
OK, I have included your fix and found an issue with it as it work intermittently - so I amended another block of code to this and it works fine now
for k := 0 to (key_cnt-1) do
keyvals[k] := Delta[i].OldValueByName[keynames[k]];
// Locates the original record
if not (ruoOnPost in oldopt)
and (BookmarkValid(bm)) then
begin
if Assigned(fOnMergeDeltaUnknownChange) then fOnMergeDeltaUnknownChange(Self, fDelta,Delta[i]);
Continue;
end
else begin
First;
if not Locate(pkfields, keyvals, []) then begin
if Assigned(fOnMergeDeltaUnknownChange) then fOnMergeDeltaUnknownChange(Self, fDelta,Delta[i]);
Continue;
end;
end;
Thank you so much for providing a part solution, it pointed to me the right area!
OK, I have included your fix and found an issue with it as it work intermittently - so I amended another block of code to this and it works fine now
for k := 0 to (key_cnt-1) do
keyvals[k] := Delta[i].OldValueByName[keynames[k]];
// Locates the original record
if not (ruoOnPost in oldopt)
and (BookmarkValid(bm)) then
begin
if Assigned(fOnMergeDeltaUnknownChange) then fOnMergeDeltaUnknownChange(Self, fDelta,Delta[i]);
Continue;
end
else begin
First;
if not Locate(pkfields, keyvals, []) then begin
if Assigned(fOnMergeDeltaUnknownChange) then fOnMergeDeltaUnknownChange(Self, fDelta,Delta[i]);
Continue;
end;
end;
Thank you so much for providing a part solution, it pointed to me the right area!