Announcement

Collapse
No announcement yet.

Allgemeine Frage zur Entwicklung an A.Kosch

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

  • Allgemeine Frage zur Entwicklung an A.Kosch

    Sollte man bei einem großen Projekt in dem sehr viele Prozeduren
    vorkommen, jeder Prozedur eine eigene ADODataSet, ADOCommand Komponente einbinden.
    Oder sollte man versuchen eine ADODataSet einzusetzen und diese variabel,
    durch das Programm, zu bearbeiten
    (Hat natürlich ADODataSet.refresh zur Folge).
    Wird durch eine große Anzahl das Programm sehr groß und damit langsam.
    Gibt es ein Mengengerüst für Komponenten wie ADODataSet.
    Wie verhält man sich bei sehr großen Datenbank Strukturen und Anwendungen ?
    Danke !

  • #2
    Hallo,

    ADO Express ist nur ein Aufsatz auf die nativen ADO-Objekte (COM-Objekte) von Microsoft. Daher macht der Einsatz von ADO Express nur dann Sinn, wenn man die Vorteile der visuellen Konfiguration über den Objektinspektor ausnutzt. Das "Umbiegen" im Sourcecode ist nicht sinnvoll, statt dessen würde ich alles fest zuordnen und die Funktionalität auf <b>mehrere</b> Datenmodule aufteilen, die erst zur Laufzeit erzeugt und zerstört werden. Alle diese Datenmodule können auf das gemeinsame Haupt-Datenmodul und somit auf eine gemeinsame TADOConnection-Instanz zugreifen. Wenn man immer nur die Datenmodule bei Bedarf erzeugt, die gerade benötigt werden und wenn man diese Instanzen wieder zerstört, gibt es keine negativen Auswirkungen.

    Kommen die verschiedenen Datenmodule aus irgend einem Grund nicht in Frage, würde ich komplett auf ADO Express verzichten und das Ganze mit den nativen ADO-Objekten umsetzen. Wenn dort erst mal ein RecordSet-Objekt erzeugt wurde, kann dieses später immer noch an eine "neutrale" TADODataSet-Instanz angehängt werden, damit über TDataSource die üblichen Komponenten nutzbar sind. In diesem Fall wird TADODataSet überhaupt nicht konfiguriert (weder im Objektinspektor noch im Sourcecode), da TADODataSet die Einstellungen vom "angehängten" ADO-RecordSet-Objekt übernimmt

    Comment


    • #3
      -> Andreas

      Hallo,
      ich verstehe den letzten Abschnitt nicht so richtig. Was bedeutet:

      "kann dieses später immer noch an eine "neutrale" TADODataSet-Instanz angehängt werden"

      Was bedeutet dieses anhängen ?

      Danke
      Gruß Mathia

      Comment


      • #4
        Hallo,

        angenommen, man hat über den nativen Zugriff auf die ADO-Objekte ein "lebendes" RecordSet erzeugt (ltBatchOptimistic) und in einer Interface-Variable abgelegt:
        <pre>
        var
        aRS : _RecordSet;
        </pre>
        Dann kann man im 2. Schritt dieses RecordSet an eine TADODataSet-Instanz anhängen, damit die Daten im TDBGrid etc. dargestellt und editiert werden können:
        <pre>
        with ADODataSetSaveRS do
        begin
        Recordset := ADOInt._RecordSet(aRS);
        Active := True;
        end;
        </pre>
        Diese TADODataSet-Instanz hat <b>keine</b> Verbindung zu TADOConnection und wird auch sonst im Objektinspektor nicht konfiguriert, da es seine Eigenschaften vom angehängten RecordSet übernimmt

        Comment


        • #5
          Hallo,

          verstehe ich die Aussage Richtig. Es wird in einem "grösseren" Projekt eine <b>TADODataSet</b> -Instanz über den Objektinspektor eingefügt und konfiguriert, anschliessend alle anderen <b>_RS</b> davon abgeleitet, bzw. die Konfiguration vom eingefügten <b>ADODataSet1</b> übernommen. Der <b>.CommandText</b> (SQL-String) wird noch angepasst und das ganze aktiviert.<br><br>MfG<br>Ad

          Comment


          • #6
            Hallo,

            nein - genau umgekehrt: <br>
            1. Eine TADODataSet-Instanz wird im Datenmodul abgelegt und <b>nicht</b> geändert (konfiguriert)<br>
            2. Über andere Wege (native ADO-Objekte, COM+ Objekt einer Three-tier-Anwendung etc). holt sich das Programm einen Interface-Zeiger auf ein "lebendes" RecordSet. Dabei ist ADO Express nicht beteiligt. <br>
            3. Dieses "lebende" RecordSet-Objekt wird über die Interface-Eigenschaft von TADODataSet an die TADODataSet-Instanz angehängt. Wird nun TADODataSet geöffnet (ohne Connection, ohne CommandText) so steht die Datenmenge zur Verfügung und kann über TDataSource im TDBGrid etc. angezeigt werden. <br>
            4. Der Anwender kann die Daten nun im TDBGrid editieren <br>
            5. Für das Updaten der Datenbank wird nun das "lebende" RecordSet-Objekt wieder von TADODataSet abgehängt und auf anderem Weg (native ADO-Aufrufe, COM+ Objekt einer Three-tier-Anwendung etc.) in den Datenbestand der SQL-Datenbank eingearbeitet (UpdateBatch).

            Da mit dem angehängten RecordSet-Objekt die Datenmenge bereits feststeht, muss die TADODataSet-Instanz nicht mehr konfiguriert werden. Das Ganz funktioniert auch dann, wenn überhaupt keine Verbindung zur Datenbank besteht, d.h. die TADODataSet-Instanz ist nicht mit einer TADOConnection-Instanz verbunden. Wird die TADODataSet-Eigenschaft Active auf True gesetzt, nachdem das lebende RecordSet angehängt wurde, führt TADODataSet keine Aktionen mehr aus, um die Daten selbst zu ermitteln.

            Im Beispiel einer Three-tier-Anwendung sieht das so aus: Der Client hat keinen direkten Zugriff zur SQL-Datenbank, sondern arbeitet nur mit dem COM+ Objekt auf dem Application Server zusammen:
            <pre>
            // lebendes RecordSet-Objekt vom Server anfordern
            procedure TFormMain.ButtonCustomerClick(Sender: TObject);
            var
            FSrv : IDelphi6ManObj;
            aRS : RecordSet15;
            begin
            ADODataSetEdit.Active := False;
            FSrv := CoDelphi6ManObj.CreateRemote(cIP);
            aRS := FSrv.CustomerRS;
            ADODataSetEdit.Recordset := ADOInt._RecordSet(aRS);
            ADODataSetEdit.Active := True;
            end;

            // alle Änderungen über den Application Server in der SQL-Datenbank einarbeiten
            procedure TFormMain.ButtonDoUpdateRSClick(Sender: TObject);
            var
            aMan : IDelphi6ManObj;
            aRS : RecordSet15;
            swMsg: WideString;
            begin
            aMan := CoDelphi6ManObj.CreateRemote(cIP);
            aRS := ADODB_TLB.RecordSet15(ADODataSetEdit.Recordset);
            // nur die geänderten Datensätze sollen zum Server
            aRS.MarshalOptions := adMarshalModifiedOnly;
            aMan.DoUpdateRS(aRS, swMsg);
            ADODataSetEdit.Active := False;
            end;
            </pre&gt

            Comment


            • #7
              Hallo,
              Danke für die bisherigen Antworten.
              Wie kann ich das erzeugen und zerstören von Datenmodulen verstehen ?
              Alle Elemente erzeugen und nur das Datenmodul gleich dem Formular erzeugen und zerstören?
              Sollte man generell alle DB Zugriffe über Datenmodule steuern, oder kann es auch Sinnvoll sein die DataSet Komponenten mit den Zugewiesenen Prozeduren direkt im Form zu plazieren.
              Dadurch wird ebenfalls ein erzeugen und zerstören realisiert.

              Sollte man eigentlich generell auf die VCL Komponenten verzichten und die nativen ADO-Objekte einsetzen und alles von Hand programmieren.

              Eine kleine Performancefrage: Ich verzichte innerhalb meiner Forms auf alle Datengebundenen Komponenten. Ich ermittle die Daten mit Select Anweisungen und erneuere sie mit Update Befehlen.
              Somit habe ich immer nur kurze Verbindungen zur Datenbank.
              Ich habe eigen Komponenten entwickelt die diese Realisierung durchführen.
              Ist dies so verbreitet und Sinnvoll. ?

              mfg Michae

              Comment


              • #8
                Hallo,

                zur Frage 1 (dynamisches Erzeugen/Zerstören von Datenmodulen): <br>
                Unmittelbar, bevor das entsprechende Formular erzeugt und angezeigt wird, erzeugt man eine Instanz des dazugehörenden Datenmoduls. Wird das Formular geschlossen und zerstört, wird auch das dazugehörende Datenmodul zerstört:
                <pre>
                procedure TFormMain.ActionEditPublikationExecute(Sender: TObject);
                begin
                DMPublikation := TDMPublikation.Create(self);
                try
                with TFormEditPublikation.Create(self) do
                try
                ShowModal;
                finally
                Release;
                end;
                finally
                DMPublikation.Free;
                end;
                end;
                </pre>
                Ab Delphi 6 steht die ObjectView-Anzeige auch für normale Formulare zur Verfügung, so dass die Vorteile beim Auslagern auf Datenmodule nicht mehr so gravierend sind wie bei Delphi 5.

                zur Frage 2 (ADO vs. ADO Express): <br>
                Das hängt von der Einsatzumgebung ab. Wenn man Objekte für Three-tier-Anwendungen entwickelt, die auf Mehrprozssor-Rechnern laufen sollen, wird man für seine Bequemlichkeit (ADO Express) mit Abstürzen (Threadfestigkeit) bestraft, so dass man freiwillig auf die nativen ADO-Objekte wechselt. In einer normalen Anwendung, bei der es nicht auf jede Millisekunde ankommt, gibt es jedoch keinen Grund, auf ADO Express zu verzichten. Allerdings stellt ADO Express nicht alle Möglichkeiten von ADO zur Verfügung, so dass im konkreten Einzelfall auch hier eine Ausnahme von der Regel sinnvoll ist.

                zur Frage 3 (Performance): <br>
                Generell ist bei SQL-Datenbanken der Zugriff über Stored Procedure, die alles über Input- und Output-Parameter abwickeln, am schnellsten. In diese Stored Procedures kann man einen grossen Teil der Anwendungs-Logik und Plausibilitätsregeln unterbringen. In diesem Kontext macht der freiwillige Verzicht auf die datengebundenen Komponenten schon Sinn. Mit TADOStoredProc führt dieser Ansatz auch nur zu einer kleinen Aufwandssteigerung für uns, da die Aufstellung aller Parameter von Delphi im Hintergrund automatisch erledigt wird

                Comment


                • #9
                  Hallo,<br><br>Ich stehe etwas verunsichert in der ADO-Entwicklungswelt. <br><br>Der Ansatz von Andreas ist zwar verständlich und trotzdem habe ich ein konzeptionelles Problem. Es stellt sich folgende Frage: <br><br>Wie sieht ein "lebendes" <b>RecordSet</b> beim Zugriff auf einen MS-SQL 7.0 aus ?<br>Ich war der Meinung (respektiv, das es der richtige Weg ist), wenn man über die VCL-Komponente <b>TADOConnection</b> die <b>OLE DB Provider</b> -Verbindung erstellt und alle <b>TADODataSet</b> über den Property <b>.connection</b> auf TADOConnection verbindet. <br>Mich verunsichert nun, ob dieser Weg nun der eigentliche "Richtige" für grössere, "universell" gehaltene Projekte ist. Wenn ich das Forum so durchforsche (ist ziemlich gross geworden), werden doch auf sehr unterschiedliche Ansätze entwickelt, was mich wieder verwundert, ob diese wirklich auch alle wissen, dass sie mit ihrem Wissen, auf dem konzeptionell, für ihr Projekt, Richtigen Weg sind.<br><br>Wenn es zu meiner Aussage oben (TADOConnection und TADODataSet) einen besseren Weg geben sollte, würde mich diesen konseptionellen Vorgang sehr interessieren (wenn möglich mit etwas Source-Code).<br><br>Mitteilung an <b>Andreas</b>, ich besitze das Buch "COM/DCOM und COM+". Wenn es da bereits ein Source-Beispiel geben sollte an das ich mich "klammern" könnte; welches Beispiel ist das und in welchem Kapitel kann ich dieses finden ?<br><br>MfG<br>Ad

                  Comment


                  • #10
                    Hallo,<br><br>ich bin nun in der ADO-Entwicklung etwas verunsichert.<br><br>Es stellt sich nun die Frage, ob ich für mein Projekt (mehrere Clients mit Zugriff auf den MS SQL 7.0 Server) auf dem Richtigen Weg bin.<br><br>Folgende Frage stellen sich:<br>Wie sieht ein "lebendes" <b>RecordSet</b> beim Zugriff auf einen MS-SQL 7.0 aus ?<br>Ich war der Meinung (respektiv, das es der richtige Weg ist), wenn man über die VCL-Komponente <b>TADOConnection</b> die <b>OLE DB Provider</b> -Verbindung erstellt und alle <b>TADODataSet</b> über den Property <b>.connection</b> verbindet. <br>Mich verunsichert nun, ob dieser Weg nun der eigentliche "Richtige" für grössere, "universell" gehaltene Projekte ist. Wenn ich das Forum so durchforsche (ist ziemlich gross geworden), werden doch auf sehr unterschiedliche Ansätze entwickelt, was mich wieder verwundert, ob diese wirklich auch alle wissen, dass sie mit ihrem Wissen, auf dem konzeptionell, für ihr Projekt, Richtigen Weg sind. <br><br>Wenn es einen besseren Weg als, wie oben beschrieben TADOConnection und TADODataSet, geben sollte, würde mich den konzeptionelle Vorgang sehr interessieren (wenn möglich mit etwas Source-Code).<br><br>
                    Mitteilung an <b>Andreas</b>, ich besitze das Buch "COM/DCOM und COM+". Wenn es da bereits ein Source-Beispiel geben sollte an das ich mich "klammern" könnte; welches Beispiel ist es und in welchem Kapitel kann ich es finden ?<br><br>
                    MfG<br>Ad

                    Comment


                    • #11
                      Hallo,

                      ich fange mit der letzten Frage an: <br>
                      Im <i>COM/DCOM/COM+ mit Delphi</i>-Buch taucht ADO nur im Zusammenhang mit Three-tier-Datenbankanwendungen (Kapitel 15 und 16) auf. Ein "richtiges" ADO-Buch ist zur Zeit in Arbeit, wird aber vor Jahres-Ende nicht erhältlich sein.

                      zum Thema "lebendes" RecordSet: <br>
                      ADO unterscheidet zwischen 2 Cursor-Architekturen: <br>
                      a) server-seitiger Cursor <br>
                      b) client-seitiger Cursor <br>
                      Während der serverseitige Cursor (clUseServer) dem entspricht, was man von der klassischen C/S-Datenbankentwicklung kennt (Client hat ständig eine offene Datenbankverbindung), arbeitet der client-seitige Cursor (clUseClient) nach einem völlig anderen Prinzip. Wird ein clUseClient-Cursor geöffnet, holt sich ADO auf dem schnellsten Weg (SQL Server 7/2000: <i>Firehouse-Cursor</i>) <b>alle</b> Datensätze dieser Datenmenge auf die Clientseite. Die Datenbankverbindung zum SQL-Server <b>darf</b> danach optional getrennt werden, ohne das "lebende" Recordset zu beeinträchtigen. Der Client kann nun diese Daten editieren, ohne eine Verbindung zur Datenbank zu haben. Erst dann, wenn alle Änderungen eingearbeitet werden sollen (Methode UpdateBatch), wird die Datenbankverbindung wieder benötigt. Man muss dies aber nur dann machen, wenn sich sehr viele Clients wenige Datenbankverbindungen gemeinsam teilen sollen (automatischer Datenbank-Verbindungspool von OLE DB) oder wenn bestimmte Nachschlagetabellen vor Ort auf dem Client-Rechner zwischengepuffert werden sollen, um die Netzlast zu minimieren.

                      Zur Zeit hat man also bei ADO die Wahl zwischen dem "alten Weg" (clUseServer) und dem "neuen Weg" (clUseClient). Erst mit ADO.NET steht nur noch der neue Weg zur Verfügung. Und beim neuen Weg hat man dann die Wahl zwischen der permanenten TADOConnection-Verbindung (ltOptimistic, die auch dann offengehalten wird, wenn der Firehouse-Cursor fertig ist und automatisch geschlossen wurde) und der optionalen getrennten TADOConnection-Verbindung (ltBatchOptimistic). In einer typischen C/S-Anwendung (kein Web, kein Three-tier) ist <b>clUseClient</b> und <b>ltOptimistic</b> der übliche Weg.

                      Ab dem übernächsten Heft von DER ENTWICKLER startet eine Artikelserie, die umfassender auf die prinzipiellen Aspekte von ADO eingeht. ADO als "eierlegende Wollmilchsau" ist verblüffend flexibel, so dass man die ADO-Objekte für verschiedenste Datenbanken konfigurieren kann, um zum Beispiel die prinzipiellen Unterschiede zwischen MS ACCESS und MS SQL Server so gut wie es geht zu überbrücken.

                      &#10

                      Comment


                      • #12
                        Hallo,<br><br>verstehe ich das richtig ?<br>1. Mit <b>TADOConnection.Active = TRUE</b> erstelle ich einen "Kanal" zum Server.<br>2. Mit <b>TADODataSet.Active = TRUE</b> erstelle ich eine "virtuelle" Verbindung im "Kanal" zum Server. (mit Konfig.: <b>clUseClient</b> und <b>clOptimistic</b>)<br><br>Wenn ich nun eine Datenmenge, wie z.B. <b>TADODataSet.CommandText = 'Select * From XY'</b> vom Server hole, öffnet der Provider (z.B.: OLE DB ...) physisch die Verbindung zum Server und holt die Datenmenge ab und schliesst anschliessend die Verbindung wieder.<br><br>D.h. nun für den Entwickler, dass er auf dem Server ein Mechanismus einbauen muss, sobald ein Anwender ein Datensatz zum Bearbeiten öffnet, das dieser für die anderen Anwender als "in Bearbeitung" gesperrt wird. usw.<br><br>Weiter folgt nun, dass man über <b>TADOConnection</b> mehrere (möglich auch Unterschiedliche, durch Provider-Typen gesetzte) Kanäle erstellt und via <b>TADODataSet</b>, die Art der Verbindung festgelegt werden kann, über diese dann die Datenmenge abholt oder zum Server sendet.<br>Wenn nun meine Schlussfolgerung dem Entspricht, was <b>ADO</b> macht, glaube ich, dass bei mir ein Lichtlein aufgegangen ist.<br><br>MfG<br>Ad

                        Comment


                        • #13
                          Hallo,

                          zu 1: Ja <br>
                          zu 2: Ja ("virtuelle Verbindung" = <b>Cursor</b> auf die Ergebnismenge der SELECT-Abfrage, die vom SQL-Server aufgebaut wurde)

                          Wenn mit <b>clUseClient</b> und ltOptimistic eine SELECT-Abfrage ausgeführt wird, hält ADO hinter den Kulissen den Cursor auf die Ergebnismenge des SQL-Server nur solange offen, wie für die Übertragung der Daten mit Hilfe des sogenannten <i>Firehouse</i>-Cursors (der schnellste Cursor, den es beim MS SQL Server gibt) benötigt wird. Danach ist die ADO-Verbindung (Connection) immer noch offen, aber der Cursor ist zu und es werden <b>keine</b> Ressourcen auf der Server-Seite mehr belegt. Somit sind jedoch keine pessistischen Sperrverfahren mehr möglich (d.h. ein Datensatz kann nicht über längere Zeit gesperrt werden)

                          Comment


                          • #14
                            Hallo,<br><br>wie sieht es mit den <b>Performance</b> und <b>Ressourcen</b> aus ?<br><br>Ist es angebracht nur mit einem "Kanal" (Connection) zu arbeiten oder gibt es eine Regel nach der es Sinnvoll wäre, mit mehreren zu arbeiten ?<br><br>Projekt-Beispiel:<br>1..2 <b>Haupt-Tabellen</b>, bei welchen neue Records hinzugefügt, Records gelöscht oder bearbeitet werden und 10..20 <b>Hilfstabellen</b>, welche hauptsächlich als Datenlieferanten dienen, aber auch durch einen Master geändert werden können.<br><br>Ist es nun Sinnvoll, 2 "Kanäle" zu erstellen, einer für die Haupttabellen und den anderen für die Hilfstabellen oder ist das "blödsinn" und man arbeitet ausschliesslich mit nur einem "Kanal" ?<br><br>MfG<br>Ad

                            Comment


                            • #15
                              Hallo,

                              bei ADO hat der Entwickler auf die Anzahl der offenen Connections <b>keinen</b> Einfluss, da ADO automatisch hinter den Kulissen neue Connections öffnet, wenn eine Funktion aufgerufen wird, die wegen der Auslastung der "alten" Leitung eine neue Verbindung benötigt. Daher würde ich alles über eine gemeinsame Connection (TADOConnection) laufen lassen, solange keine separate Transaktions-Steuerung benötigt wird.

                              Für Neugiere stellt der SQL Server einen Weg bereit, wie man diesen Mechanismus beobachten kann: Über <i>Start | Einstellungen | Systemsteuerung | Verwaltung</i> wird der <b>Systemmonitor</b> aufgerufen, dort kann über den +-Button ein neuer Leistungsindikator (<i>SQLServer: Allgemeine Statistik | Benutzerverbindungen</i>) hinzugefügt werden.

                              Der Vorteil des client-seitigen Cursors (clUseClient) liegt ja gerade darin, dass die Server-Ressourcen nur für die Dauer der reinen Datenübertragung über den <i>Firehouse</i>-Cursor belegt werden. Danach verwirft der SQL Server alle belegten Ressourcen, da der Client dank der <i>OLE DB Cursor Engine</i> nur noch lokal mit den Daten ("lebendes RecordSet") arbeitet.
                              &#10

                              Comment

                              Working...
                              X