Bevorzugte Art und Weise Delphi-Datenbank zu schreiben apps mit Transaktionen und datensensitiven Komponenten

StackOverflow https://stackoverflow.com/questions/3833432

Frage

Was ist der bevorzugte Weg Delphi Datenbank-Anwendungen unter Verwendung von Transaktionen zu schreiben und auch datensensitiven Komponenten?

Ich habe eine Client-Anwendung zu schreiben, dass der Zugang InnoDB-Tabellen, und einige Master-Detail-Art von Dingen innerhalb von Transaktionen. einige der Forschung auf Transaktionen (von allgemeinen Point-of-View) Nachdem ich, dann mache ich demütig eine Schlussfolgerung, dass nicht datensensitiven Komponenten und handcodierte SQL der „perfect match“ von Transaktionen wären; Aber die datensensitiven Komponenten wären nicht. Sie scheinen nicht für sie gemacht werden.

Ich habe den tatsächlichen Bedarf zu verwenden Transaktionen, aber auf der anderen Seite konnte ich nicht nur die datensensitiven Komponenten wegzuwerfen, weil sie erheblich vereinfachen Dinge.

Könnte jemand bitte mich aufklären? Ich habe googeln, aber ich habe keine nützliche Antwort gefunden. Vielleicht, weil mein Englisch ist nicht gut genug, dass meine Keywords begrenzt sind.

BTW, ich bin mit Delphi 7 und zur Zeit UniDAC als Datenzugriffsbibliothek auszuwerten.

Danke.

Bearbeiten

Beispiel einen Aspekt meiner Frage zu beschreiben:

Stellen Sie sich ein Formular mit 2 DBGrids darauf. Das erste Gitter ist MasterGrid und darüber sind diese Schaltflächen: Hinzufügen, Bearbeiten und Löschen. Das zweite Gitter ist DetailGrid. Wenn der Benutzer klicken Sie auf Hinzufügen, dann gehen sie wie folgt aus:

  • Connection.StartTransaction
  • Master.Append dann Master.Post dann Master.Edit (so die Hauptdatenmenge die autoincrement Primärschlüssel hat, und es ist editierbar jetzt) ??
  • Zeigen Sie modal Editierformular, in dem der Benutzer die Stammsätze füllt, und auch einige Detaildatensätze unter Verwendung eines anderen Form hinzufügen.
  • Wenn der Benutzer auf OK klicken, würde die App tun Master.Post und Connection.commit. Wenn der Benutzer auf Abbrechen klicken, dann würde die App Connection.rollback tun.

ich weiß, dass Transaktionen so kurz wie möglich sein sollen, aber Sie können oben sehen, dass die Transaktion nur so kurz wie die Geschwindigkeit des Benutzers das Formular ausfüllen.

Wenn ich nicht datensensitiven Komponenten verwendet wurden, würde ich benutzerdefinierte Einsatz SQLs machen aus Benutzereingaben basiert, dann die SQL zwischen Starttransaction ausführen und Commit. Also habe ich sehr kurze Transaktion erreichen kann.

EDIT 2

Ich danke Ihnen allen für Ihre freundliche Teilnahme. Ich nehme die Antwort von vcldeveloper, weil es in der Nähe Lösung zu meinem aktuellen Bedarf.

War es hilfreich?

Lösung

Andere erwähnt eine Kombination aus DataSetProvider und ClientDataSet unter Verwendung eines Batch-Update haben, aber im Falle von Komponenten ADO oder UniDAC verwenden, brauchen Sie nicht die Extraschicht DataSetProvider + ClientDataSet, weil beide ADO und UniDAC unterstützt Batch-Updates.

ADO , was Sie tun sollten, ist auf LockType Ihres Datensatzes ltBatchOptimistic . Für UniDAC , sollten Sie CacheUpdate Eigenschaft auf True .

Diese Änderung macht die Datenmenge um alle Änderungen cachen Sie auf seiner In-Memory-Cord machen, und nur sie ALLtogether zur Datenbank senden, wenn Sie anrufen Update Methode (ADO) oder ApplyUpdates Methode (UniDAC).

Nun, was Sie tun sollten, ist Ihr Benutzer einfügen / bearbeiten einen Datensatz in der Hauptdatenmenge zu lassen und was zeichnet er / sie will in den Details Datensatzes mit was auch immer datensensitiven Komponenten, die Sie mögen. Alle Änderungen würden zwischengespeichert werden. Wenn Ihre Benutzer fertig ist, können Sie eine neue Transaktion zu starten, und ersten Aufruf Update (oder ApplyUpdate bei UniDAC) für die Hauptdatenmenge, und dann für die Details Datenmenge, und wenn alles gut geht, um die Transaktion begehen.

Dies wird Ihre Transaktionen kurz machen, ohne die zusätzliche Schicht ClientDataSet zu benötigen.

Viele Grüße

Andere Tipps

Ich verstehe Ihre Frage, glaube ich. Beim Öffnen eines TADODataSet mit z.B. 10 Reihen von Daten in einem Formular bearbeitet werden, mit datensensitiven Komponenten, gibt es Situationen, in denen Sie alle Änderungen in dem Cache gemacht, um alle der 10 Reihen (und möglicherweise Deletionen und Insertionen) und begehen sie als eine Charge wollen würden . Sie können die Transaktion nicht auf der ersten Änderung öffnen, denn das würde andere Benutzer blockieren, die gleichen Daten zu ändern. Transaktionen sollten so kurz wie möglich sein.

Was ich in skizzierte Szenario zu tun ist, um die folgenden Komponenten in einer Kette verwenden:

TADOConnection >> TADODataSet >> TDataSetProvider >> TClientDataSet >> TDataSource >> TDBEdits etc.

Jetzt werden alle Änderungen in TClientDataSet zwischengespeichert und Sie können es Methode ApplyUpdates rufen alle Änderungen in einer schnellen Transaktion zu veröffentlichen. Versteht, dass es auch möglich, mehrere TADODataSets und mehrere TClientDataSets für ein Master-Detail (-detail-etc) Struktur mit verschachtelten Datensatz zu verwenden. Alle Master-Detail-Änderungen auch im Cache gespeichert werden können und in einer Charge in einer Transaktion angewandt. Sehen Sie sich die Hilfe und Ressourcen an anderer Stelle für alle Details über diese umzusetzen. Zunächst ist es nicht einfach. Aber wenn Sie es herausgefunden ist es einfach und bietet jede Menge Möglichkeiten. (Offline-Bearbeitung, Prüfung Änderungen vor ihrer Anwendung, etc.)

, um die Notwendigkeit zu vermeiden, große Transaktionen auszuführen ich DataSetProviders und ClientDataset (auch vor Ort).

Betrachten Sie dies als eine Art Cache verwendet und es gibt Ihnen das Beste aus beiden Welten. Sie können datensensitiven Steuerelemente verwenden, um Dinge zu vereinfachen, während auf der Benutzeroberfläche arbeiten. Benutzeraktionen über die Datensätze werden „aufgezeichnet“ durch die ClientDataSets (Art von Datenbank-Cache).

Wenn Sie Ihre Benutzer bereit sind, zu Speichern die Änderungen an der Datenbank (beispielsweise die Rechnungsdaten ist alles an seinem Platz), rufen Sie die ApplyUpdates Methode für den Datensatz (s).

Im einfachsten Fall, in dem alle Datensätze sind in Master-Detail-Beziehung (vom Provider verschachtelt), der Anbieter startet und Commits / Rollbacks die Transaktion von selbst, so dass Sie sich in einem alles oder nichts Situation sind automatisch.

Wenn Sie komplexere Beziehungen haben, können Sie vor dem Starttransaction rufen starten Updates für jeden beteiligten ClientDataSet Sätze anwenden, und am Ende Aufruf Commit oder Rollback nach Bedarf). Die Logik für den Anbieter ist, wenn die Verbindung eine aktive Transaktion hat, wenn ApplyUpdates genannt wird, dann tut es nichts mit der Transaktion, sondern einfach Post Änderungen an Datenbank, vorausgesetzt, Sie die Kontrolle über die Transaktion sind.

Sie haben über TClientDataSet zu lesen und wie die OnReconcileError und Experiment mit der Technik zu behandeln, bevor es in Produktionsumgebungen setzen, aber es funktioniert sehr, sehr gut für mich.

Meine 2 Cent.

Sie haben völlig Recht, dass ein Schreib Transaktion so kurz wie möglich sein sollte, und es soll nicht am Leben die ganze Zeit, während ein Benutzer das Formular ausfüllt.

Die allgemeine Lösung, wie bereits beantwortet, ist eine Zwischenebene (a ClientDataSet) zu verwenden. Aber das eigentliche Problem mit Ihrem Szenario ist, dass Sie nicht einen autoincrement-Wert für die Master-Tabelle ohne Master.Append und Master.Post erhalten können und damit beginnen Sie eine write Transaktion, lange bevor es tatsächlich erforderlich ist.

Also, wenn Sie nicht wollen, dass die Zwischenebene verwenden und immer noch verwenden datensensitiven Komponenten mit kurzen write Transaktionen, die Sie von einer Datenbank sollten denken, dass Träger ohne einen autoinkrementierten Wert zu erhalten INSERT ausführt (zu Master-Tabelle). Das Beispiel ist Firebird Datenbank und FIBPlus Datenzugriffskomponenten für Firebird voll unterstützen diese Funktion.

Transaktionen so kurz sein sollten als erforderlich . Das Problem ist, wie verschiedene Datenbanken Griff zu verriegeln. Datenbanken, die nur ausführen Sperren auf Zeilenebene und kann sofort von einem Verschluss zurück, ohne zu warten hat, weit weniger probabilty Deadlock. Normalerweise Einsätze sind weniger problematisch (obwohl andere Benutzer keine neuen Zeilen bis verpflichtet sehen werden, abhängig von der Isolationsstufe), Aktualisierungen und Löschungen sind problematischer. zu oft begehen könnte „schlecht“ als gut. Caching von Änderungen und sie in einem einzigen Betrieb der Anwendung ist eine weitere Möglichkeit - aber man muss Griff Probleme aufgrund anderer Benutzer zu ändern mittlerweile Aufzeichnungen. Es gibt keine eine „bessere“ Lösung - alles hängt von den tatsächlichen Bedürfnissen. Für einige Anwendungen (und einige Datenbanken) halten den Rekord so lange gesperrt, wie sie ändern sich in Ordnung, für andere nicht. Batch-Updates kann in einigen Szenarien und in anderen nicht in Ordnung sein. Sie haben das Modell zu wählen, das am besten für Ihre Anwendung und Datenbank funktioniert.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top