3-Tier MessageTable does not work

montgomb

Member
Using Delphi 6; DataSnap; DOA 345.

Problem: TOracleDataSet.UseMessageTable does not work in a 3-Tier application.

Description: After having already created the server and client applications I tried to make use of the TOracleDataSet.UseMessageTable features and found that the client did not receive translated messages during the reconcile process. I have the DOA source code so I began tracing into the source and found that when applying updates to the application server through the providers TOracleDataSet is using an internal TOracleQuery to execute the update (insert, update, or delete) SQL statements. TOracleQuery does not make use of the MessageTable in the session component and that appears to be why the client is not receiving translated messages. I don't know if all this is correct but I do know the client is not receiving translated messages. Is there a way to use the MessageTable features when developing a 3-tier application?
 
The message translation only works if TDataSetProvider.ResolveToDataSet = True.

In your situation it will not work, for the reason you already found out. You could consider adding an exception handler for EOracleError exceptions that calls TranslatedMessage:

DatabaseError(TranslatedMessage(C, E.ErrorCode, E.Message));

The C parameter would have to be 'I', 'U', or 'D' for an Insert, Update or Delete. E is the EOracleError that was raised.

We will consider this change ourselves.

------------------
Marco Kalter
Allround Automations
 
Originally posted by mkalter:
The message translation only works if TDataSetProvider.ResolveToDataSet = True.

In your situation it will not work, for the reason you already found out. You could consider adding an exception handler for EOracleError exceptions that calls TranslatedMessage:

DatabaseError(TranslatedMessage(C, E.ErrorCode, E.Message));

The C parameter would have to be 'I', 'U', or 'D' for an Insert, Update or Delete. E is the EOracleError that was raised.

We will consider this change ourselves.


Where is the best place in the middle tier to put the exception handler?
 
I noticed that I didn't mention this, but the idea was that you modify the TOracleDataSet.PSExecuteStatement source, and translate the exception where it occurs.

Like I said, we will consider this change in a future patch release.

------------------
Marco Kalter
Allround Automations
 
The best I could come up with is to modify the TOracleQuery.ExecuteArray method. It seems to work but I would like your opinion.

function TOracleQuery.ExecuteArray(Index, Count: Integer): Integer;
var Continue: Boolean;
Offset, ArraySize: Integer;
QueryType : Char; //added by Bruce Montgomery 30 August 2001
begin
Result := 0;
if Count = 0 then Exit;
FState := qsExecuting;
try
if Assigned(FBeforeQuery) then FBeforeQuery(Self);
CallAfterQuery := True;
if (Count = -1) and (Index = -1) then
begin
ArraySize := 0;
Offset := 0;
end else begin
ArraySize := Index + Count;
Offset := Index;
end;
Continue := True;
repeat
try
InternalExecute(False, True, ArraySize, Offset);
Inc(Result, RowsProcessed);
Continue := False;
except on E:EOracleError do
begin
//Bruce Montgomery 30 August 2001
//Provides error translation for TOracleQuery when
//TOracleQuery is being used by a TOracleDataSet
//to ApplyUpdates.
case FunctionType of //
5 : QueryType := 'U';
9 : QueryType := 'D';
3 : QueryType := 'I';
else
QueryType := '*';
end; // case
if Owner is TOracleDataSet then
E.Message := TOracleDataSet(Owner).TranslatedMessage(QueryType, E.ErrorCode, E.Message);
//end of changes by Bruce Montgomery
if ArraySize = 0 then ArraySize := ArrayBindSize;
Inc(Offset, RowsProcessed + 1);
Inc(Result, RowsProcessed);
if Assigned(FOnArrayError) then
FOnArrayError(Self, Offset - 1, E.ErrorCode, E.Message, Continue)
else begin
if (Count = -1) and (Index = -1) then raise;
Continue := False;
end;
if Offset >= ArraySize then Continue := False;
end;
end;
until not Continue;
if Eof then
begin
if CallAfterQuery and Assigned(FAfterQuery) then FAfterQuery(Self);
CallAfterQuery := False;
end;
finally
FState := qsIdle;
end;
end;
 
I personaly would not dare to apply this change at such a low level. You should consider changing TOracleDataSet.PSExecuteStatement as suggested in my previous message.

------------------
Marco Kalter
Allround Automations
 
Originally posted by mkalter:
I personaly would not dare to apply this change at such a low level. You should consider changing TOracleDataSet.PSExecuteStatement as suggested in my previous message.


I could not figure out how to modify TOracleDataSet.PSExecuteStatement. Could you reply with a changed TOracleDataSet.PSExecuteStatement that does the job?
 
I have sent you a modified PSExecuteStatement by e-mail.

------------------
Marco Kalter
Allround Automations
 
Back
Top