Announcement

Collapse
No announcement yet.

DataSnap, DCom und com

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

  • DataSnap, DCom und com

    Ich habe vor, eine mehrschichtige Anwendung mit den Delphi 6 DataSnap Komponenten zu entwickeln.

    Jedoch werde ich aus dem Delphi 6 Buch nicht ganz schlau, wozu genau diese Komponenten dienen. Ich hab' es so verstanden, als seien die Komponenten dazu da, Tabellen und alle Art von Queries zu übertragen, es jedoch die Möglichkeit gibt, zusätzliche Schnittstellen zu implementieren. Entfremde ich die Komponenten von ihrem eigentlichen Zweck, wenn ich sie nur zum Prozeduraufruf verwende?

    Außerdem bekomme ich keine Verbindung von einem entfernten Client hin, startet man den Client auf dem Rechner, auf dem der Server läuft, funktionert mein Aufruf, versuche ich jedoch von einem anderen Rechner zuzugreifen, bekomme ich die Fehlermeldung "Schnittstelle wird nicht unterstützt".

  • #2
    Hallo,

    rein technisch gesehen sind die DataSnap-Komponenten nicht notwendig. Aus betriebswirtschaftlicher Sicht machen diese Dinger selbstverständlich Sinn, da man für den Einsatz einer rechnerübergreifenden DataSnap-Anwendung (Server und Client sind nicht auf dem gleichen Rechner) bei Borland eine Lizenz je Server <b>kaufen</b> muss (ca. 300US$), wobei dieser Vorgang bei jedem Delphi-Upgrade wiederholt werden muss (da sich in der Vergangenheit jedesmal auch die MIDAS-Versionsnummer geändert hat).

    Ich habe alle meine Three-tier-Datenbankanwendungen ohne MIDAS/DataSnap entwickelt (wobei nicht so sehr das Geld eine Rolle spielte, sondern die Probleme, die MIDAS/DataSnap auf Multiprozessor-Servern hat). Da die kostenlos verfügbaren ADO-Objekte von Microsoft die Funktionalität von MIDAS/DataSnap abdecken und zudem tatsächlich auch auf Multiprozessor-Maschinen völlig Threadfest sind, kommen bei mir die VCL-Komponenten (ADO Express) erst in der Benutzeroberfläche (Client) ins Spiel. Auch mit den ADO-Objekten stehen die Übertragungswege DCOM und HTTP (über das ebenfalls kostenfreie RDS von Microsoft) zur Verfügung. Der Einsatz von ADO hat zudem den großen Vorteil, dass Microsoft einen direkten Migrationsweg in die .NET-Welt zur Verfügung stellt.

    Auf der EKON 6 (6. Entwickler-Konferenz) gehe ich im Montag-Workshop den ganzen Tag auf die Implementierungs-Alternativen einer Three-tier-Anwendung ein. Die Kurzfassung ist aber auch am Dienstag in der Konferenz-Session <i>Von DCOM zu SOAP mit Delphi 5/6</i> zu hören.

    &gt;..Fehlermeldung "Schnittstelle wird nicht unterstützt".

    Für dieses Problem gibt er 2 Ursachen:

    1. Die Typbibliothek (*.tlb) des Servers wurde nicht auf dem Client-Rechner installiert. Da Delphi "Trittbrett" fährt und den Universal-Marshaler des Betriebssystem nutzt (also den Hilfsweg, den Microsoft für Visual Basic 3 eingebaut hat), muss das Betriebssystem auf beiden Rechnern auf die Typbibliothek zugreifen können, um erst zur Lauzeit die von DCOM benötigten Proxy-/Stub-Objekte zusammenzubauen. Im Bin-Unterverzeichnis von Delphi ist das Tool <b>TRegSrv.exe</b> zu finden, mit dem man die .TLB-Datei auf dem Client registriert kann.

    2. Ein DCOM-Rechteproble

    Comment


    • #3
      Hallo Andreas,

      der Nachteil der Kosten von DataSnap soll mit Delphi 7 wegfallen, da mit dem Erwerb einer Delphi-Enterprise-Version alle Kosten abgegolten sein sollen (Wenn man den Nachrichten von John Caster in der Newsgroup borland.public.delphi.non-technical trauen darf). Wahrscheinlich hat Borland gemerkt das bei 3000 US$ pro Server jeder sich nach einer Alternative umgesehen hat

      Comment


      • #4
        Hallo Bernhard,

        Borland hat den MIDAS/DataSnap-Preis erst dann von 5000 US$ je Server zuzüglich 100 US$ je Client auf 300 US$ (ohne Client-Lizenzen) gesenkt, als mit Delphi 5 die ADO Express-Komponenten in Delphi enthalten waren und somit die kostenfreie Alternative für jeden sichtbar/verfügbar war.

        Mit dem Auftauchen von .NET und ADO.NET schwimmen Borland in diesem Punkt die letzten Felle weg, denn der Leistungsumfang des kostenfreien ADO.NET liegt um ganze Größenordnungen über dem von DataSnap. Und da Borland die .NET-Version von Delphi offiziell angekündigt hat, wird der Nischenplatz von DataSnap in Zukunft noch winziger, als er jetzt schon ist

        Comment


        • #5
          Vielen Dank für die Infos, dann werd' ich meine Applikation mit Hilfe der ADO-Komponenten entwickeln.

          Aber eine Sache hab' ich da noch, und zwar ob ich über diese Komponenten bzw. Objekte auch ganze Tabellen oder Queries übergeben kann und ob das Management auch wie bei den DataSnap Komponenten schon implementiert ist oder ob ich die Zugriffe dann alle über Methoden des Interface leiten müsste...

          Vielen Dank im Voraus

          Comment


          • #6
            Hallo,

            in ADO wird die Ergebnismenge einer SELECT-Abfrage im <i>Recordset</i>-Objekt abgelegt. Diese Recordset-Objektinstanz kann (bei getrennter Datenbankverbindung) später zu jeden beliebigen Rechner transportiert werden, wobei über den Transportweg RDS (Remote Data Services) sogar HTTP als Protokoll zur Verfügung steht.

            Auf dem Anwendungs-Server (Application Server wie zum Beispiel Windows 2000) wird das eigene COM+ Objekt installiert, welches ein Interface zur Verfügung stellt, das vom Client aufgerufen werden kann. Der Client übergibt beim Aufruf eine SELECT-Zeichenkette und erhält ein "lebendes" Recordset mit der Ergebnismenge seiner Abfrage zurück. Zur Vereinfachung greife ich beim folgenden Beispiel auf ADO Express zurück und ignoriere auch die übergebenen SQL-Anweisung:
            <pre>
            function TFXDBObjReadOnly.GetRS(const sName: WideString): _Recordset;
            begin
            try
            try
            ADOConnection1.Connected := True;
            ADODataSet1.Active := True;
            Result := ADODB_TLB._Recordset(ADODataSet1.Recordset);
            ADODataSet1.Connection := nil;
            ADODataSet1.Close;
            SetComplete;
            finally
            ADOConnection1.Connected := False;
            end;
            except
            SetAbort;
            raise;
            end;
            end;
            </pre>
            Der Client hängt das erhaltende "lebende" Recordset an eine TADODataSet-Instanz an und kann somit die Daten im TDBGrid anzeigen:
            <pre>
            uses ADOInt;

            procedure TForm1.Button1Click(Sender: TObject);
            var
            aSrv : IFXDBObjReadOnly;
            aRS : Recordset15;
            swName : WideString;
            begin
            aSrv := CoFXDBObjReadOnly.Create;
            aRS := ADOInt._Recordset(aSrv.GetRS(swName));
            ADODataSet1.Recordset := _Recordset(aRS);
            ADODataSet1.Active := True;
            end;
            </pre>
            Der Rückweg (Client übergibt das lokal geänderte Recordset-Objekt, damit der Application Server die Änderungen einarbeiten kann) sieht genauso aus. Nur dass das COM+ Objekt nach dem Wiederherstellen der Datenbankverbindung am Ende die Recordset-Methode <b>UpdateBatch</b> aufruft. Über die <b>MarshalOption</b>-Eigenschaft des Recordsets kann der Client festlegen, dass nur die geänderten Datensätze des Recordsets zurück zum Server transportiert werden.

            &gt;..ob ich die Zugriffe dann alle über Methoden des Interface leiten müsste..

            Auf ein COM/COM+ Objekt kann nur über die Interface-Methoden zugegriffen werden, somit wird ein Interface <b>zwingend</b> benötigt. Mit MIDAS/DataSnap steht zwar ein Vorgabe-Interface zur Verfügung, aber in einer nicht-trivialen Anwendung reicht dieser schlichte Weg nicht aus, so dass man auch bei MIDAS/DataSnap eigene Interface-Methoden nachrüsten muss. Der Aufwand an dieser Stelle ist somit gleich - allerdings hat man bei der eigenen Lösung jederzeit die absolute Kontrolle über das Ganze.

            Wenn zum Beispiel vom Server nur ein Datensatz abefordert werden soll, macht es aus Performancegründen Sinn, eine Stored Procedure aufzurufen, die die Daten nur als OUTPUT-Parameter (aber nicht als Ergebnismenge) zurückliefert. In diesem Fall muss die eigene Interface-Methode die Daten ebenfalls als OUT-Parameter der Interface-Methode zurückliefern (wobei diese Interface-Methode nur für diesen konkreten Fall eingesetzt werden kann). Das könnte zum Beispiel so aussehen:
            <pre>
            CREATE PROCEDURE GetGIFromKD_NR_N
            @kd_nr_n INTEGER,
            @sOutnachname_firma1_t VARCHAR(33) OUTPUT,
            @sOutvorname_firma2_t VARCHAR(33) OUTPUT,
            @sOutPLZ CHAR(10) OUTPUT,
            @sOutORT VARCHAR(27) OUTPUT
            AS
            DECLARE @iRowCount INT
            -- Transaktion starten
            SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
            BEGIN TRANSACTION
            --
            SELECT
            @sOutnachname_firma1_t = i.nachname_firma1_t,
            @sOutvorname_firma2_t = i.vorname_firma2_t,
            @sOutPLZ = i.plz_t,
            @sOutORT = i.ort_t
            FROM KD i
            WHERE i.kd_nr_n = @kd_nr_n
            -- Anzahl der Treffer zwischenspeichern
            SELECT @iRowCount = @@ROWCOUNT
            -- Stored Procedure regelt alles selbst, kein DTC
            COMMIT TRANSACTION
            Return @iRowCount
            </pre>
            Implementierung der Interface-Methode im COM+ Objekt:
            <pre>
            function TFXDBObjReadOnly.GetGIFromKdnNr(kd_nr_n: Integer; out firma1,
            firma2, PLZ, ORT: WideString): Integer;
            begin
            try
            try
            ADOConnection1.Connected := True;
            with ADOStoredProcGetGIFromKD_NR_N do
            begin
            Parameters[1].Value := kd_nr_n;
            ExecProc;
            if Parameters[0].Value > 0 then
            begin
            firma1 := Parameters[2].Value;
            firma2 := VarToStr(Parameters[3].Value);
            PLZ := Parameters[4].Value;
            ORT := Parameters[5].Value;
            end
            else
            begin
            firma1 := '';
            firma2 := '';
            PLZ := '';
            ORT := '';
            end;
            Result := Parameters[0].Value;
            end;
            SetComplete;
            finally
            ADOConnection1.Connected := False;
            end;
            except
            SetAbort;
            raise;
            end;
            end;
            </pre>
            In meinen Büchern <i>ADO und Delphi</i> (siehe http://www.entwickler.com/itr/buecher/show.php3?id=7&nodeid=92) und <i>COM/DCOM/COM+ mit Delphi</i> (siehe http://www.entwickler.com/itr/buecher/show.php3?id=17&nodeid=92&ps_lo=20) wird das Thema erschöpfend erschlagen :-

            Comment

            Working...
            X