Jump to content

How to display clientdataset errors?


rsanford

Recommended Posts

  • Administrators

Would like to try something like Showmessage(E.Message) in the OnReconcileError or OnPostError event but no luck. Any suggestions appreciated.

Thanks

 

In web mode ShowMessage can only be called inside a web event context. i.e. any event which is initiated from browser.

 

Where does OnReconcileError or OnPostError occur? Inside a web request or elsewhere?

Link to comment
Share on other sites

In web mode ShowMessage can only be called inside a web event context. i.e. any event which is initiated from browser.

 

Where does OnReconcileError or OnPostError occur? Inside a web request or elsewhere?

 

I'll write you from my philosophical point of view. Almost all the procedures that I run in data module are functions that return actually a boolean value that tells me whether or not executed properly. That is, the Data Module is only for that, to contain no visible components such as queries, stored procedures, tables, etc ... and I ask it do something from the visual interface. If the answer is false, indicating that an error occurred and it is deposited in a field of the data module with the error description.

 


type
TStandardDataModule =
 class( TDataModule )
  private
   fErrorCode: Integer;
   fAdInfo: String;

   function GetErrorMsg: String;

  protected
   function OpenTable( aTable: TTable ): Boolean;


  public

   function RefreshUsers: Boolean;

   property ErrorCode: Integer read fErrorCode;
   property ErrorMsg: String read GetErrorMsg;
   property AdInfo: String read fAdInfo;
 end;

implementation

function TStandardDataModule.GetErrorMsg: String;
begin
 Result := TranslateToStringErrorCode(fErrorCode); // Take it from resources
end;

function OpenTable( aTable: TTable ): Boolean;
begin
 try
  aTable.Open;

  Result := True;
 except
  on E: Exception
   begin
    Result := False;
    fErrorCode := rcErrorOpenningTable;
    fAdInfo := E.Message;
   end;
 end;
end;

function TStandardDataModule.RefreshUsers: Boolean;
begin
 tblUsers.Close;

 Result := OpenTable(tblUsers);
end;

 

Then I call it from other places in the application more or less like:

 


procedure ShowUsersList;
begin
 if DataModule.RefreshUsers
  then UsersForm.Show
  else ShowErrorMessage(DataModule.ErrorMsg, DataModule.AdInfo);
end;  

 

ShowErrorMessage( const aErrorMsg, aAdInfo: String; aCallBack: TClassMethod = Nil);

 

ShowErrorMessage is a proxy function to MessageDlg to avoid to write every time [mtError], [mbOk] parameters...

 

In the web case you can add CallBack method if you want to return back to some place due the threads are managed.

 

I do this because I want to show the user a message understandable by him, and show the exception message for technical support.

 

“Give to Caesar what is Caesar’s, and give to God what is God’s.”

 

At the end, the DataModule is a BRIDGE between database and visual interface, is not what the user would see. It give to UI what to show, Records from tables, queries, or just message of good execution or error message of bad execution of insert, updates and deletes.

 

In the Standard Client/Server application (in VCL) you could "use" dialogs unit and use then ShowMessage directly from DataModule. But in this case your UI in one machine and the DM is another machine, or the IU is running in "client process" and the DM in "server process". Although they are running on the same machine are not running in the same processes' space.

Link to comment
Share on other sites

This works for me. Added for any web event that updates the client dataset. What can be done on the web side is still a grey area for me.

 

 

begin
try
   UniMainModule.cdsFacility.ApplyUpdates(0);
 except
   on E: Exception do
   begin
     raise Exception.Create('Apply updates error: ' + E.Message + ' Please contact support.');
   end;
 end;
end;

Link to comment
Share on other sites

This works for me. Added for any web event that updates the client dataset. What can be done on the web side is still a grey area for me.

 

 

begin
try
   UniMainModule.cdsFacility.ApplyUpdates(0);
 except
   on E: Exception do
   begin
     raise Exception.Create('Apply updates error: ' + E.Message + ' Please contact support.');
   end;
 end;
end;

 

Check this out:

 

In UniMainModule:

 


function TUniMainModule.ApplyUpdatesToFacility(var aErrorMsg: String): Boolean;
begin
 try
   UniMainModule.cdsFacility.ApplyUpdates(0);

   Result := True;
  except
   on E: Exception do
    begin
     Result := False;
     aErrorMsg := 'Apply updates error: ' + E.Message + ' Please contact support.';
    end;
 end;
end;

 

On the WEB (Forms) side:

 


procedure UniButton1.Click(Sender: TObject);
var
 ErrorMsg: String;

begin
 if UniMainModule.ApplyUpdatesToFacility(ErrorMsg)
  then MessageDlg('Data was saved sucefully', mtConfirmation, [mbOk])
  else MessageDlg(ErrorMsg, mtError, [mbOk])
end;

 

 

In this case from the web (forms) side you call method to apply updates and if it would be without any problem you just confirm it, and if would be any error you can show it.

 

Sometime I use to show just when an error has been ocurred, and I use this:

 

 


procedure UniButton1.Click(Sender: TObject);
var
 ErrorMsg: String;

begin
 if not UniMainModule.ApplyUpdatesToFacility(ErrorMsg)
  then MessageDlg(ErrorMsg, mtError, [mbOk])
end;

Link to comment
Share on other sites

  • 2 weeks later...

Check this out:

 

In UniMainModule:

 


function TUniMainModule.ApplyUpdatesToFacility(var aErrorMsg: String): Boolean;
begin
 try
   UniMainModule.cdsFacility.ApplyUpdates(0);

   Result := True;
  except
   on E: Exception do
    begin
     Result := False;
     aErrorMsg := 'Apply updates error: ' + E.Message + ' Please contact support.';
    end;
 end;
end;

 

Hi,

 

In my test, after excecuting the line UniMainModule.cdsFacility.ApplyUpdates(0), for example, even if an error occurs,

it does not come in except block, not generating the exception, only the error code reported is > 0.

Any idea why not enter except block?

 

Tks.

Link to comment
Share on other sites

Thank you Dionel, I appreciate your assistance. I plan to rewrite error handling soon and will integrate your suggestions.

 

Sorry for the time of my answer, but I've been super busy.

 

I am not a great programmer, but I follow a lot metaphors in programming. In this case there is one metaphor that says, "to Caesar what is Caesar's, to God what is God." I'm honest, it is sometimes difficult to follow for many reasons, but I always try to do it.

 

post-125-0-29194300-1315653191_thumb.jpg

 

The image of the post can give you an idea of ​​what I'm talking about. For me, the windows (forms) are the tier 1 and are the interface with the user. TForms, TDialogs are the Delphi components (Delphi-ExtPascal-ExtJS) for the interface with user. The servermodule is part of the tier 2 and MainModule resides at the tier 2 but is the interface with the database and/or database server. TTable, TQuery, TStoreProc, they are not the DataBase elements, they are the components of Delphi to link with database elements. Database elements are the tier 3.

 

Now, where may be the confusion? You develop forms as part of the server, but not actually used there, they travel through the network to present the user, and the communication protocols send back request to server. With those requests you do some actions with database elements through db Delphi components. Then, the result of the actions in handling the data are server-side and somehow the result of the actions are sent back to the customer. It could be as a list of somethings or just an error message caused by somewhat.

 

PS: The image is not mine. I took it from:

 

http://virtualadrian.com/2007/02/12/building-a-stupid-client-part-1/

 

I do not read the text. Just search in google/images an appropiate image to write here.

Link to comment
Share on other sites

Sorry for the time of my answer, but I've been super busy.

 

I am not a great programmer, but I follow a lot metaphors in programming. In this case there is one metaphor that says, "to Caesar what is Caesar's, to God what is God." I'm honest, it is sometimes difficult to follow for many reasons, but I always try to do it.

 

post-125-0-29194300-1315653191_thumb.jpg

 

The image of the post can give you an idea of ​​what I'm talking about. For me, the windows (forms) are the tier 1 and are the interface with the user. TForms, TDialogs are the Delphi components (Delphi-ExtPascal-ExtJS) for the interface with user. The servermodule is part of the tier 2 and MainModule resides at the tier 2 but is the interface with the database and/or database server. TTable, TQuery, TStoreProc, they are not the DataBase elements, they are the components of Delphi to link with database elements. Database elements are the tier 3.

 

Now, where may be the confusion? You develop forms as part of the server, but not actually used there, they travel through the network to present the user, and the communication protocols send back request to server. With those requests you do some actions with database elements through db Delphi components. Then, the result of the actions in handling the data are server-side and somehow the result of the actions are sent back to the customer. It could be as a list of somethings or just an error message caused by somewhat.

 

PS: The image is not mine. I took it from:

 

http://virtualadrian.com/2007/02/12/building-a-stupid-client-part-1/

 

I do not read the text. Just search in google/images an appropiate image to write here.

 

 

Hi Dieonel,

 

As I put in my previous post, after running the ApplyUpdates (0), even if the error occurs, does not enter except block .. that does not identify with the message to display to the user ..

 

Any idea?

 

Regards.

Link to comment
Share on other sites

  • Administrators

Check this out:

 

In UniMainModule:

 


function TUniMainModule.ApplyUpdatesToFacility(var aErrorMsg: String): Boolean;
begin
 try
   UniMainModule.cdsFacility.ApplyUpdates(0);

   Result := True;
  except
   on E: Exception do
	begin
     Result := False;
     aErrorMsg := 'Apply updates error: ' + E.Message + ' Please contact support.';
	end;
 end;
end;

 

Hi,

 

In my test, after excecuting the line UniMainModule.cdsFacility.ApplyUpdates(0), for example, even if an error occurs,

it does not come in except block, not generating the exception, only the error code reported is > 0.

Any idea why not enter except block?

 

Tks.

 

You call UniMainModule inside TUniMainModule? Why?

Link to comment
Share on other sites

You call UniMainModule inside TUniMainModule? Why?

 

Hi Farshad,

 

I do not call the code above, just put this code as an example.

In my call I have a class (TModelClass) where it and execute the methods:

 

unit Model

 

interface

..

..

 

TModelClass = class

..

..

function Post (var aErrorMsg: String): boolean;

..

 

Implementation

 

uses SessionModule;

 

function TModelClass.Post(var aErrorMsg: String): boolean;

begin

Result: = False;

if dmSessionModule.cdsAtivities.ChangeCount > 0 then

begin

try

dmSessionModule.cdsAtivities.ApplyUpdates(0);

Result := True;

except

on E: Exception do

begin

Result := False; / / never enters this block, even with error in ApplyUpdates ..

aErrorMsg := 'Apply updates error:' + E. Message + 'Please contact support.';

end;

end;

end;

end;

Link to comment
Share on other sites

Check this out:

 

In UniMainModule:

 


function TUniMainModule.ApplyUpdatesToFacility(var aErrorMsg: String): Boolean;
begin
 try
   UniMainModule.cdsFacility.ApplyUpdates(0);

   Result := True;
  except
   on E: Exception do
    begin
     Result := False;
     aErrorMsg := 'Apply updates error: ' + E.Message + ' Please contact support.';
    end;
 end;
end;

 

Hi,

 

In my test, after excecuting the line UniMainModule.cdsFacility.ApplyUpdates(0), for example, even if an error occurs,

it does not come in except block, not generating the exception, only the error code reported is > 0.

Any idea why not enter except block?

 

Tks.

 

Sorry for the delay in response. I'm not sure, because long ago I do not use the dbExpress development of the applications, but I think ApplyUpdates does an internal management of exceptions and it only returns an integer that tells you if errors occurred or not and / or how many errors occurred in the execution of the method. So, may be this is the cause. Then you can change your code and take in consideration to return False if it return a value greater than zero.

 

Sometimes I have a big problem with DB Engines, because they do not send me back the message of occurred errors. So, in that case I show just an error message in Spanish without the message from DB Engine, and that is a big problem when I have to make a technical assistance.

 

Luckily for me, that happens sometimes and in most cases I try to check all the fields in the user input at least to avoid these problems, i.e. errors caused by absence of the field value, or a missing field value.

 

Sorry again if you have not been helpful by my answer, but right now I have nothing to say about it.

Link to comment
Share on other sites

Hi Dionel!

 

Yes. DBXpress returns an integer value with the number of errors, or 0(sucess). The exception generated for example by TDataSetProvider is captured in

the client by OnReconcilerError event. We need a way to use for example the OnReconcilerError event and trigger the error through a "raise Exception" to the client. Currently it is only generated in the log file, without the user having knowledge of the errors are managed by business rules. Many validations are handled in the server layer (DataSnap server) and must be properly propagated to the client, especially those that are generated by TDataSetProvider.

Let's hope something new by Farshad concerning this point.

 

Thanks for your important attention,

 

Best Regards.

Link to comment
Share on other sites

Hi Dionel!

 

Yes. DBXpress returns an integer value with the number of errors, or 0(sucess). The exception generated for example by TDataSetProvider is captured in

the client by OnReconcilerError event. We need a way to use for example the OnReconcilerError event and trigger the error through a "raise Exception" to the client. Currently it is only generated in the log file, without the user having knowledge of the errors are managed by business rules. Many validations are handled in the server layer (DataSnap server) and must be properly propagated to the client, especially those that are generated by TDataSetProvider.

Let's hope something new by Farshad concerning this point.

 

Thanks for your important attention,

 

Best Regards.

 

just up...

Link to comment
Share on other sites

  • 3 weeks later...
  • Administrators

Hi Dionel!

 

Yes. DBXpress returns an integer value with the number of errors, or 0(sucess). The exception generated for example by TDataSetProvider is captured in

the client by OnReconcilerError event. We need a way to use for example the OnReconcilerError event and trigger the error through a "raise Exception" to the client. Currently it is only generated in the log file, without the user having knowledge of the errors are managed by business rules. Many validations are handled in the server layer (DataSnap server) and must be properly propagated to the client, especially those that are generated by TDataSetProvider.

Let's hope something new by Farshad concerning this point.

 

Thanks for your important attention,

 

Best Regards.

 

Well, as I told before, all expections that occur in context of a web event are handled and sent back to the browser.

It seems that under certain conditions it doesn't work as expected. Can you create a test project for your case?

Link to comment
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • Create New...