Search code examples
delphifiredac

FireDac connection issue


I was using an example from here :

establishing connection

Did it this way :

procedure TDataModule2.DataModuleCreate(Sender: TObject);
begin
with FDGUIxLoginDialog1.VisibleItems do begin
  Clear;
  Add('Server=Strežnik');
  Add('User_name=Uporabnik');
  Add('Password=Geslo');
  Add('Database=Baza');
end;
try
FDConnection1.Connected := True;
except
  on E: EAbort do
  application.terminate;   // user pressed Cancel button in Login dialog

  on E:EFDDBEngineException do
    case E.Kind of
    ekUserPwdInvalid: ; // user name or password are incorrect
    //ekUserPwdExpired: ; // user password is expired
    ekServerGone: ;     // DBMS is not accessible due to some reason
    else
                 // other issues
    end;
end;
end;

However, application will not terminate after hitting cancel in the login dialog but shows my main form. What should I do to correct this ?

Also, how can I flash a message if the password was wrong, in this scenario ?

Firedac is connecting to SQL Server.

ps

Even this will not work :

.....
except
  on E: EFDDBEngineException do
  if E.Kind = ekUserPwdInvalid then
      begin
        ShowMessage('A user name or a password are invalid');
        Abort;
      end;

Solution

  • An application usually quits by closing its main form.
    You should never let an application quit by issuing an exception; it's bad form.

    EAbort is not an exception that gets issued by the login dialog. In fact under normal circumstances te login dialog will not issue any exception.
    If the user presses Cancel then the connection will not get ehm.. connected, you can test that.
    Here's a list of all the errors TFDConnection can generate.

    The following code should work:

    type
      TAction = (aSuccess, aGiveup, aWrongPassword, aPasswordExpired);
    
    procedure TDataModule2.DataModuleCreate(Sender: TObject);
    var
      VI: TStrings; 
      WhatToDo: TAction;
    begin
      WhatToDo:= aSuccess;
      VI:= FDGUIxLoginDialog1.VisibleItems; 
      VI.Clear;
      VI.Add('Server=Strežnik');
      VI.Add('User_name=Uporabnik');
      VI.Add('Password=Geslo');
      VI.Add('Database=Baza');
      try
        FDConnection1.Connected := True;
      except
        on E:EFDDBEngineException do case E.Kind of
          ekUserPwdInvalid: WhatToDo:= aWrongPassword;
          ekUserPwdExpired: WhatToDo:= aPasswordExpired;
          else WhatToDo:= aGiveUp;
        end; {case}
      end;
      if Not(FDConnection1.Connected) then WhatToDo:= aGiveUp;
      case Action of
        aWrongPassword: begin
          ShowMessage('You've entered a wrong username or password please try again');
          DataModuleCreate(Sender);
          Action:= aSuccess;
        end;
        aPasswordExpired: ShowMessage('You password has expired, please request a new one from the PHB');
      end;
      if Action <> aSuccess then Application.Terminate;
    end;
    

    Comments about coding style
    Do not use with. With is evil use a temporary variable instead and use that to reference the nested variable(s).

    Terminating on an error without issuing an error is really silly.
    No user is going to be happy having an application die on them without any explanation why.

    You should never terminate on a wrong password or username.
    As least give the user the change to try again 3 or 4 times.
    If he doesn't get it right by then issue the "wrong username or password" error message and quit.
    Never tell the user which (username or password) is wrong, an attacker can use that to generate a list of usernames.