Announcement

Collapse
No announcement yet.

Anwendung IBCSDEMO aus A. Kosch C/S Buch

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Anwendung IBCSDEMO aus A. Kosch C/S Buch

    Hallo, leider kann ich das Programm IBCSDemo aus dem Buch Client Server Datenbankentwicklung von H. Kosch nicht starten. Ich bekomme die Meldung: "Unbekannte Datenbank Alias _IBCSDMain". Außerdem such ich die OSUDF5.DLL. Ich arbeite mit Delphi 5 und Interbase 5.5. Was muß ich tun damit das Programm läuft. Das was im Buch steht habe ich gelesen, wollte nun mit dem Programm üben. Vielen Dank für Hinweise. Gruß ph.

  • #2
    Hallo,

    auf der Seite 591 (im Kapitel 18) ist vermerkt, was alles an Vorbereitungen (UDF-DLL und BDE-Alias <i>IB_BuchIBCSDemo</i>) zu erledigen ist. Die dort genannte OSUDF5.DLL wird im Kapitel 16 auf den Seiten 504 bis 512 vorgestellt und ist im Sourcecode auf der CDROM zum Buch im Verzeichnis <i>Kapitel 16\UDFs</i> zu finden.

    Da im Datenmodul gleich 2 TDataBase-Instanzen (für jeden Thread eine) verwendet werden, greift die Anwendung auf "virtuelle Alias-Namen" (über die TDataBase-Eigenschaft <b>DatabaseName</b>) zurück, die jedoch immer auf den BDE-Aliasnamen IB_BuchIBCSDemo basieren:
    <pre>
    object DatabaseMain: TDatabase
    AliasName = 'IB_BuchIBCSDemo'
    DatabaseName = '_IBCsdMain'
    Params.Strings = (
    'USER NAME=SYSDBA'
    'SQLPASSTHRU MODE=SHARED AUTOCOMMIT'
    'ENABLE BCD=TRUE'
    'WAIT ON LOCKS=FALSE'
    'ROLE NAME='
    'PASSWORD=')
    SessionName = 'SsnMain'
    TransIsolation = tiRepeatableRead
    OnLogin = DatabaseMainLogin
    Left = 112
    Top = 8
    end
    </pre>

    &gt;Ich bekomme die Meldung: "Unbekannte Datenbank Alias _IBCSDMain".

    Diese Fehlermeldung gehört zu der folgenden Zeile in der DFM-Datei IBCSDemoDM.dfm:
    <pre>
    DatabaseName = '_IBCsdMain'
    </pre>
    Ich gehe davon aus, das zur Zeit der BDE-Alias <i>IB_BuchIBCSDemo</i> noch nicht eingerichtet wurde (siehe Seite 591)

    Comment


    • #3
      <br>Hallo Herr Kosch, wahrscheinlich bin ich mal wieder zu dämlich <br>das im Buch geschriebene nachzuvollziehen.
      <br>Im Debug-Modus erhalte ich jetzt die Meldung: IBCSDemo.ExE <br>Excepition... Es ist ein Wert für das Feld erforderlich.
      <br>In der Programmzeile Result := True;
      <br>
      <br>function TDM.DBLogin: Boolean;
      <br>begin
      <br>...
      <br>...
      <br>Result := True;
      <br>except
      <br>...

      Comment


      • #4
        Hallo,

        wenn das Programm gestartet wird, blendet es aus dem Datenmodul heraus den Login-Dialog ein, um den Benutzernamen und das Passwort zwischenzuspeichern:
        <pre>
        ...
        uses DBLogDlg, IBCSDemoMainForm, IBCS_SdxSearchThrd;

        {$R *.DFM}

        {
        TDatabase.OnLogin wickelt die Abfrage nach dem Paßwort für den
        Benutzer SYSDBA ab. Da die zweite TDatabase-Verbindung für den
        zweiten Thread auch geöffnet werden muß, aber nur eine Paßwortabfrage
        ausreichen soll, speichert das Datenmodul sowohl den Benutzernamen
        als auch das Paßwort in eigenen Objektfeldern, um später darauf
        zurückgreifen zu können.
        }

        procedure TDM.DatabaseMainLogin(Database: TDatabase;
        LoginParams: TStrings);
        var
        sUser : String;
        sPwd : String;
        begin
        sUser := 'SYSDBA';
        sPwd := '';
        if LoginDialogEx('IBCSDemo', sUser, sPwd, True) then
        begin
        FDBUser := sUser;
        FDBPwd := sPwd;
        LoginParams.Values['USER NAME'] := FDBUser;
        LoginParams.Values['PASSWORD'] := FDBPwd;
        end;
        FDBAlias := DatabaseMain.Aliasname;
        end;

        {---------------------------------------------------------------}
        { Öffentliche Methoden des Datenmoduls }
        {---------------------------------------------------------------}

        {
        Anwender meldet sich an der Datenbank an -> 2 TDatabase öffnen.
        Beim Aufruf von »DatabaseMain.Connected := True;« wird implizit
        das OnLogin-Ereignis aufgerufen und der Login-Dialog wird angezeigt.
        Dabei speichert das Datenmodul Benutzername und Paßwort in eigenen
        Objektfeldern, so daß diese Werte für die zweite TDatabase-Instanz
        einfach wiederverwendet werden.
        }

        function TDM.DBLogin: Boolean;
        begin
        Result := False;
        try
        DatabaseMain.Connected := True;
        QueryPROCGetOrt.Prepare;
        StoredProcInsertKunde.Prepare;
        with DatabaseThread do
        begin
        Params.Values['USER NAME'] := FDBUser;
        Params.Values['PASSWORD'] := FDBPwd;
        end;
        DBRefreshAnrede;
        Result := True;
        except
        //
        end;
        end;
        ...
        </pre>

        Der Aufruf erfolgt aus dem Hauptformular heraus, indem der entsprechende Button/Menüeintrag angeklickt wird und somit die TActionList-Komponente ins Spiel kommt:
        <pre>
        procedure TFormMain.ActionLoginExecute(Sender: TObject);
        begin
        FLogin := DM.DBLogin;
        StatusBar1.SimpleText := Format('BDE-Alias: %s', [DM.DBAlias]);
        end;
        </pre>
        Um nun der Ursache für dieses Problem auf die Schliche zu kommen, würde ich in der Methode <i>TFormMain.ActionLoginExecute</i> einen Breakpoint in die Zeile <i>FLogin := DM.DBLogin</i> setzen und dann das Programm schrittweise ausführen. An welcher Stelle springt der Debugger aus dem vorgesehenen Ablauf

        Comment


        • #5
          Hallo, nachdem ich die Anweisung DBRefreshAnrede auskommentiert habe, kann ich das Programm starten. Das Programm läuft aber nicht richtig.
          Danke Gruß ph

          Comment


          • #6
            Hallo,

            &gt;Das Programm läuft aber nicht richtig

            wenn man in einem Programm eine Programmzeile einfach auskommentiert, kann das Programm anschließend nicht mehr richtig laufen :-)

            Die folgende Implementierung der Methode DBRefreshAnrede zeigt, dass dort eine TClientDataSet-Instanz mit den Daten aus der InterBase-Tabelle gefüllt werden, um diese lokal auf dem Client-Rechner verfügbar zu machen:
            <pre>
            procedure TDM.DBRefreshAnrede;
            begin
            with ClientDataSetAnrede do
            begin
            Active := False;
            with ClientDataSetAnrede.FieldDefs do
            begin
            Clear;
            Add('ANR_ID',ftInteger,0,True);
            Add('Anrede',ftString,10,True);
            Add('Hinweis',ftString,50,False);
            end;
            CreateDataSet;
            Active := True;
            end;
            with QueryAnrede do
            begin
            Open;
            try
            while not EOF do
            begin
            with ClientDataSetAnrede do
            begin
            Append;
            ClientDataSetAnredeANR_ID.Value := QueryAnredeANR_ID.Value;
            ClientDataSetAnredeANREDE.Value := QueryAnredeANREDE.Value;
            ClientDataSetAnredeHINWEIS.Value := QueryAnredeHINWEIS.Value;
            Post;
            end;
            Next;
            end;
            finally
            Close;
            end;
            end;
            end;
            </pre>
            An welcher Stelle innerhalb dieser Methode bleibt der Debugger beim schrittweisen Abarbeiten stehen

            Comment


            • #7
              Beim vierten Post in der QueryAnrede und es kommt zu der Meldung:
              [Hinweis] IBCSDemoDM.pas(277): Auf 'TDM.DBGetOrtId' zugewiesener Wert wird niemals benutzt. Danke Gruß p

              Comment


              • #8
                Hallo,

                &gt;[Hinweis] IBCSDemoDM.pas(277): Auf 'TDM.DBGetOrtId' zugewiesener Wert wird niemals benutzt.

                das ist kein Fehler beim schrittweisen Ausführen des Projekts, sondern nur ein <i>Hinweis</i> beim Compilieren des Projekts. Die Methode <i>DBGetOrtId</i> wird ebenfalls im Datenmodul implementiert und wird innerhalb der Unit <i>IBCSDemoFrmKundeExt.pas</i> genutzt (d.h. der Delphi-Compiler irrt sich an dieser Stelle, so dass der Hinweis irrelevant ist):
                <pre>
                procedure TFormKundeExt.ComboBoxOrtExit(Sender: TObject);
                begin
                if Length(ComboBoxOrt.Text) = 0 then
                raise Exception.Create('Sie haben keinen Ort ausgewählt');
                with DM do
                QueryExtKundenORT_ID.Value := DBGetOrtId(EditPLZ.Text, ComboBoxOrt.Text);
                end;
                </pre>
                Allerdings hat die Methode <i>DBGetOrtId</i> überhaupt nicht mit der Methode <i>DBRefreshAnrede</i> zu tun. Passiert dies wirklich beim schrittweisen Ausführen des Programm im Delphi-Debugger? Wenn ja, wie sehen die einzelnen Arbeitsschritte bis dahin aus

                Comment


                • #9
                  Hallo, ich kann das Programm starten und mich einloggen. Es stehen aber keine Programmfunktionen zur Verfügung(Bis auf Programm beenden). Nach auskommentiern von DBRefresh stehen dann aber die Programmfunktionen zur Verfügung. Im Debug-Modus erscheint die Meldung wie in Antwort zwei beschrieben. Vielen Dank Gruß ph

                  Comment


                  • #10
                    Hallo,

                    &gt;..ich kann das Programm starten und mich einloggen. Es stehen aber keine Programmfunktionen zur Verfügung.

                    In diesem Fall war der Login-Vorgang nicht erfolgreich! Wurde wirklick der Login-Dialog mit dem Benutzernamen und dem Passwort angezeigt, richtig ausgefüllt und beendet? Denn nur dann, wenn das Objektfeld <i>FLogin</i> auf True gesetzt wird, schaltet die <b>TActionList</b>-Komponente auf dem Hauptformular die Programmfunktionen frei:
                    <pre>

                    <font color="#003399"><i>{--------------------------------------------------------------}</i></font>
                    <font color="#003399"><i>{ ActionList-Steuerung und OnExecute-Ereignisbehandlung }</i></font>
                    <font color="#003399"><i>{--------------------------------------------------------------}</i></font>

                    <b>procedure</b> TFormMain.ActionList1Update(Action: TBasicAction;
                    <b>var</b> Handled: Boolean);
                    <b>begin</b>
                    ActionNeuerKunde.Enabled := FLogin;
                    ActionBearbeitenKunde.Enabled := FLogin;
                    ActionShowAll.Enabled := FLogin;
                    ActionEditTQuery.Enabled := FLogin;
                    ActionEditTTable.Enabled := FLogin;
                    ActionFrmChild.Enabled := FLogin <b>and</b> FPrgIdle;
                    ActionFrmModal.Enabled := FLogin;
                    ActionFormThreadInit.Enabled := FLogin;
                    ActionLogin.Enabled := <b>not</b> FLogin;
                    ActionLogout.Enabled := FLogin;
                    Handled := True;
                    <b>end</b>;

                    </pre>
                    Das Objektfeld <i>FLogin</i> wird nur dann auf True gesetzt, wenn der Login-Vorgang über die Datenmodul-Methode <i>DBLogin</i> erfolgreich war:
                    <pre>

                    <b>procedure</b> TFormMain.ActionLoginExecute(Sender: TObject);
                    <b>begin</b>
                    FLogin := DM.DBLogin;
                    StatusBar1.SimpleText := Format(<font color="#9933CC">'BDE-Alias: %s'</font>, [DM.DBAlias]);
                    <b>end</b>;

                    </pre>

                    Die Methode <i>DBLogin</i> aus dem Datenmodul liefert nur dann der Wert True zurück, wenn <br>
                    a) der Login-Vorgang erfolgreich war, und <br>
                    b) keine andere Exception aufgetreten ist
                    <pre>

                    <b>function</b> TDM.DBLogin: Boolean;
                    <b>begin</b>
                    Result := False;
                    <b>try</b>
                    DatabaseMain.Connected := True;
                    QueryPROCGetOrt.Prepare;
                    StoredProcInsertKunde.Prepare;
                    <b>with</b> DatabaseThread <b>do</b>
                    <b>begin</b>
                    Params.Values[<font color="#9933CC">'USER NAME'</font>] := FDBUser;
                    Params.Values[<font color="#9933CC">'PASSWORD'</font>] := FDBPwd;
                    <b>end</b>;
                    DBRefreshAnrede;
                    Result := True;
                    <b>except</b>
                    <font color="#003399"><i>//</i></font>
                    <b>end</b>;
                    <b>end</b>;

                    </pre>
                    Um die Ursache für das Problem einzugrenzen, würde ich zum Test das Schlucken der Exception deaktivieren und die Methode <i>DBLogin</i> wie folgt ändern:
                    <pre>

                    <b>function</b> TDM.DBLogin: Boolean;
                    <b>begin</b>
                    Result := False;
                    DatabaseMain.Connected := True;
                    QueryPROCGetOrt.Prepare;
                    StoredProcInsertKunde.Prepare;
                    <b>with</b> DatabaseThread <b>do</b>
                    <b>begin</b>
                    Params.Values[<font color="#9933CC">'USER NAME'</font>] := FDBUser;
                    Params.Values[<font color="#9933CC">'PASSWORD'</font>] := FDBPwd;
                    <b>end</b>;
                    DBRefreshAnrede;
                    Result := True;
                    <b>end</b>;

                    </pre>
                    Welche Exception-Meldung zeigt das Programm nun zur Laufzeit über eine MessageBox an?
                    &#10

                    Comment


                    • #11
                      Es erscheint in der MessageBox:" Es ist ein Wert für das Feld erforderlich". Nach betätigen der Anmeldefunktion erscheint die Datenbank-Login-Box.
                      Benutzername SYSDBA nach Eingabe von masterkey erscheint der
                      SQL-Cursor(Sanduhr) und danach kommt nun die oben beschriebene Meldung.
                      Über den Interbase Server-Manager, Interactive SQL kann ich mit der Datenbank arbeiten.
                      Danke Gruß ph

                      Comment


                      • #12
                        Hallo,

                        &gt; Über den Interbase Server-Manager, Interactive SQL kann ich mit der Datenbank arbeiten.

                        weil dieses Tool <b>nicht</b> über die BDE auf den InterBase zugreift, könnte der Grund für die geschilderten Probleme auch in einer nicht korrekte Konfiguration des BDE-Aliases liegen. Ich würde daher als nächsten Test im <i>SQL-Explorer</i> (alias <i>Datenbank-Explorer</i>) der BDE prüfen, ob über den eingerichteten BDE-Alias die Datenbank geöffnet werden kann. Tauchen im SQL-Explorer/Datenbank-Explorer der BDE die Tabellen der Datenbank nach dem Anklicken des <b>+</b>-Zeichens vor dem Aliasnamen in der TreeView-Darstellung auf?
                        &#10

                        Comment


                        • #13
                          Hallo, im SQL-Explorer sind nach erfolgten Login (SYSDBA, masterkey) alle vier Tabellen sichtbar

                          Comment


                          • #14
                            Hallo, Information das Programm läuft jetzt. Ich habe den Interbase 6 installiert und das Programm von der CD aus dem Buch Interbase Datenbankentwicklung... genommen

                            Comment

                            Working...
                            X