Gibt es in Delphi eine Möglichkeit, Master-Detail-Zeilen zwischenzuspeichern und Master- und Detail-Child-Zeilen gleichzeitig zu posten

8

Ich möchte einige untergeordnete Zeilen im Speicher ablegen und diese dann bedingt posten oder sie nicht in einer zugrunde liegenden SQL-Datenbank ablegen, je nachdem, ob eine übergeordnete Zeile gebucht oder nicht, oder nicht. Ich brauche kein vollständiges ORM, aber vielleicht nur das:

  1. Der Benutzer klickt auf Arzt hinzufügen. Dialogfeld "Arzt hinzufügen" wird geöffnet.
  2. Bevor Sie im Feld Arzt hinzufügen auf Ok bei Arzt hinzufügen klicken, fügt der Benutzer einen oder mehrere Patienten hinzu, die nur im Speicher vorhanden sind.
  3. Der Benutzer klickt im Fenster "Arzt hinzufügen" auf OK. Jetzt sind alle Patienten und der neue Arzt eingelagert.
  4. Wenn der Benutzer im Fenster "Arzt" auf "Abbrechen" klickt, werden alle Arzt- und Patienteninformationen verworfen.

Versuchen Sie, sich geistig vorzustellen, wie Sie das Obige mit Delphi-Daten-fähigen Steuerelementen und TADOQuery oder anderen ADO-Objekten machen könnten. Wenn es eine nicht ADO-spezifische Möglichkeit gibt, dies zu tun, bin ich auch daran interessiert, ich werfe nur ADO da draußen, weil ich MS-SQL Server und ADO in meinen aktuellen Anwendungen verwende.

>

Bei früheren Arbeitgebern, bei denen ich für kurze Zeit gearbeitet habe, hatten sie eine Klasse namens TMasterDetail , die speziell dafür geschrieben wurde, das Obige ADO-Recordsets hinzuzufügen. Es funktionierte manchmal und manchmal scheiterte es an einigen wirklich interessanten und schwer zu reparierenden Wegen.

Ist etwas in die VCL eingebaut, oder in irgendeine Komponente von Drittanbietern, die eine robuste Methode besitzt? Wenn nicht, ist das, worüber ich oben gesprochen habe, ein ORM erforderlich? Ich dachte, ORMs würden von vielen Leuten als "schlecht" betrachtet, aber das oben genannte ist ein ziemlich natürliches UI-Muster, das in einer Million Anwendungen auftreten kann. Wenn ich einen Nicht-ADO-Nicht-Delphi-db-Dataset-Arbeitsstil verwenden würde, wäre das Obige kein Problem in fast jeder Persistenzschicht, die ich schreiben könnte, und wenn Datenbanken mit Primärschlüsseln Identitätswerte verwenden, um die Verbindung herzustellen Master- und Detailzeilen kommen ins Bild, die Dinge werden kompliziert.

Update: Transaktionen sind in diesem Fall kaum ideal. (Commit / Rollback ist ein zu grober Mechanismus für meine Zwecke.)

    
Warren P 07.06.2012, 20:51
quelle

1 Antwort

3

Sie stellen zwei getrennte Fragen:

  1. Wie speichere ich Updates?
  2. Wie kann ich Aktualisierungen für verknüpfte Tabellen gleichzeitig festschreiben?

Zwischengespeicherte Aktualisierungen können auf verschiedene Arten durchgeführt werden. Welche davon am besten ist, hängt von Ihrer speziellen Situation ab:

ADO Batch-Aktualisierungen

Da Sie bereits angegeben haben, dass Sie ADO verwenden, um auf die Daten zuzugreifen, ist dies eine sinnvolle Option. Sie müssen den LockType einfach auf ltBatchOptimistic und CursorType auf entweder ctKeySet oder ctStatic setzen, bevor Sie das Dataset öffnen. Rufen Sie dann TADOCustomDataset.UpdateBatch auf, wenn Sie zum Festschreiben bereit sind.

Hinweis: Der zugrunde liegende OLEDB-Anbieter muss Batch-Aktualisierungen unterstützen, um dies zu nutzen. Der Provider für SQL Server unterstützt dies vollständig.

Ich kenne keinen anderen Weg, die Master / Detail-Beziehung zu erzwingen, wenn ich die Daten persistiere, als UpdateBatch sequentiell in beiden Datensätzen aufzurufen.

%Vor%

Client-Datasets

Das Zwischenspeichern von Daten ist einer der Hauptgründe dafür, dass TClientDataset existiert und das Synchronisieren einer Master / Detail-Beziehung ist überhaupt nicht schwierig.

Dazu definieren Sie wie gewohnt die Master-Detail-Beziehung auf zwei Datenmengenkomponenten (in Ihrem Fall ADOQuery oder ADOTable ). Erstellen Sie dann einen einzelnen Anbieter und verbinden Sie ihn mit dem Master -Dataset. Verbinden Sie einen single TClientDataset mit dem Anbieter und Sie sind fertig. TClientDatset interpretiert das Detail-Dataset als verschachteltes Dataset-Feld, auf das wie in jedem anderen Dataset zugegriffen werden kann und an datensensitive Steuerelemente gebunden werden kann.

Sobald dies geschehen ist, rufen Sie einfach TClientDataset.ApplyUpdates auf und die Client-Datenmenge sorgt dafür, dass die Aktualisierungen für die Master- / Detaildaten korrekt geordnet werden.

ORMs

Es gibt eine Menge über ORMs zu sagen. Zu viel, um in eine Antwort auf StackOverflow zu passen, also werde ich versuchen, mich kurz zu fassen.

ORMs haben in letzter Zeit einen schlechten Ruf bekommen. Einige Experten sind so weit gegangen, sie als Anti-Pattern zu bezeichnen. Ich persönlich finde das ein bisschen unfair. Objektrelationales Mapping ist ein unglaublich schwieriges Problem, das richtig zu lösen ist. ORMs versuchen zu helfen, indem sie einen Großteil der Komplexität abstrahieren, die beim Übertragen von Daten zwischen einer relationalen Tabelle und einer Instanz eines Objekts involviert ist. Aber wie bei allem anderen in der Softwareentwicklung gibt es keine Silberkugeln und ORMs sind keine Ausnahme.

Für eine einfache Dateneingabeanwendung ohne viele Geschäftsregeln ist ein ORM wahrscheinlich übertrieben. Aber wenn eine Anwendung immer komplexer wird, sieht ein ORM attraktiver aus.

In den meisten Fällen sollten Sie ein ORM eines Drittanbieters verwenden, anstatt selbst zu rollen. Ein benutzerdefiniertes ORM zu schreiben, das perfekt zu Ihren Anforderungen passt, klingt nach einer guten Idee und es ist leicht, mit einfachen Mappings zu beginnen, aber Sie werden bald in Probleme wie Eltern / Kind-Beziehungen, Vererbung, Caching und Cache-Invalidation geraten aus Erfahrung). Drittanbieter-ORMs haben diese Probleme bereits kennengelernt und eine enorme Menge an Ressourcen ausgegeben, um sie zu lösen.

Bei vielen ORMs tauschen Sie die Codekomplexität für die Konfigurationskomplexität aus. Die meisten von ihnen arbeiten aktiv daran, die Standardkonfiguration zu reduzieren, indem sie sich Konventionen und Richtlinien zuwenden. Wenn Sie alle Ihre Primärschlüssel Id benennen, anstatt die Spalte Id jeder Tabelle einer entsprechenden Id -Eigenschaft für jede Klasse zuordnen zu müssen, teilen Sie dem ORM einfach diese Konvention mit und es wird davon ausgegangen, dass alle Tabellen und Klassen folgen Das Treffen. Sie müssen die Konvention nur für bestimmte Fälle außer Kraft setzen, für die sie nicht gilt. Ich bin nicht mit allen ORMs für Delphi vertraut, also kann ich nicht sagen, welche Unterstützung dies und welche nicht.

In jedem Fall sollten Sie Ihre Anwendungsarchitektur so gestalten, dass Sie die Entscheidung, welches ORM-Framework (oder welches Framework) Sie verwenden möchten, so lange wie möglich unterdrücken können.

    
Kenneth Cochran 28.06.2012, 17:43
quelle

Tags und Links