Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi DELPHI-Fehler in Master/Detail-Verknüfungem über MasterFields (https://www.delphipraxis.net/215334-delphi-fehler-master-detail-verknuefungem-ueber-masterfields.html)

daddy 14. Jun 2024 12:33

Datenbank: Firebird • Version: 3 • Zugriff über: TClientDataSet

DELPHI-Fehler in Master/Detail-Verknüfungem über MasterFields
 
Ich bin dabei ein Projekt von Delphi 7 auf Delphi 11 zu migrieren und habe ein Problem, das ich damals durch einen eigenen Eingriff in die Delphi-Quellcodes gelöst habe, das aber überraschenderweise auch in Delphi 11 immer noch besteht.

Es geht um eine VCL-Anwendung mit Firebird-Anbindung. Der Zugriff auf Firebird erfolgt über TClientDataSets, die über TDataSetProvider mit TSQLDataSets kommunizieren. An vielen Stellen werden Master-Detail-Verknüpfungen benötigt. Diese werden bereitgestellt, indem im TClientDataSet der Detailtabelle die Eigenschaften "MasterSource", "MasterFields" und "IndexFieldNames" gefüllt sind. Bei einfachen SQL-Selects funktioniert das auch:

Beispiel Master:
Delphi-Quellcode:
Select * from Liefeant

Beispiel Detail:
Delphi-Quellcode:
Select * from LieferantKontakt


Die Tabelle Lieferant hat ein Feld "Nummer", die Tabelle Kontakt ein Feld "LNummer", das sich auf das Feld Nummer bezieht. Mein Programm verhält sich genauso wie gewünscht.

Meistens sind die Detailtabellen aber ein wenig komplexer aufgebaut und stellen auch Daten anderer Tabellen bereit. Und dies führt zwangsläufig zu Fehlermeldungen von Delphi, egal ob Version 7 oder 11.
Hier einfache Beispiele für nicht funktionierende Abfragen, bei denen zur Tabelle LieferantKontakt noch ein Bezeichner aus einer Tabelle KontakArt geholt wird:
Detail:
Delphi-Quellcode:
Select L.*, K.Bezeichnung from LieferantKontakt left join KontaktArt K on L.KANummer = K.Nummer

oder
Delphi-Quellcode:
Select L.*, (Select K.Bezeichnung from KontaktArt where Nummer = L.KANummer) as Bezeichnung from LieferantKontakt


Ich habe per Debugging im Delphi-Quellcode die Funktion "AddParamSQLForDetail" in der Unit "Data.DBCommon.Pas" als Ursache für das Problem herausgefunden, die einfach fehlerhaft arbeitet und offensichtlich nur mit einfach gestrickten Anweisungen der Art "Select * from <Table> order by <Column>" zurechtkommt. Weder Joins noch Unterselects werden in irgendeiner Form korrekt erkannt und berücksichtigt. Das in meinem obigen Beispiel von der Funktion eingefügte "where LNummer = ?" landet in diesen Fällen an der falschen Stelle und führt somit zu einer ungültigen Select-Anweisung.
Natürlich könnte ich das Problem irgendwie umschiffen oder wieder - wie damals bei Delphi 7 - den delphieigenen Code korrigieren. Aber das erste macht mir aufgrund des Projektumfangs ziemlich viel Aufwand und das zweite zwingt mich bei jedem Delphi-Update die Korrekturen erneut vorzunehmen.

Kennt irgend jemand von euch (oder von Embarcadero) dieses Problem und hat evtl. eine bessere Lösung?

Sinspin 14. Jun 2024 13:02

AW: DELPHI-Fehler in Master/Detail-Verknüfungem über MasterFields
 
Ich verwende FireDac zum zugriff auf alle DB und mache alles selber, dann muss sich FD nicht was ausdenken:
Code:
SELECT L.*, K.Bezeichnung
FROM LieferantKontakt L
LEFT JOIN KontaktArt K ON L.KANummer = K.Nummer
WHERE L.Nummer = :MasterField
ORDER BY L.Whatever
Ich hatte mit dieser Methode noch nie Probleme.
Noch MasterFields und DetailFields eintragen um FD noch ein bisschen weiter entgegen zu kommen... aber das muss nicht sein.

himitsu 14. Jun 2024 13:29

AW: DELPHI-Fehler in Master/Detail-Verknüfungem über MasterFields
 
Hat devart auch direkt was für Firebird?

Wir nutzen pgDAC für den Zugriff auf PostreSQL.
OK, inzwischen auch an einigen Ecken schonmal FireDAC (das war aber vor allem wegen des LocalSQL)

Uwe Raabe 14. Jun 2024 13:48

AW: DELPHI-Fehler in Master/Detail-Verknüfungem über MasterFields
 
Zitat:

Zitat von himitsu (Beitrag 1537760)
Hat devart auch direkt was für Firebird?

IBDAC oder UniDAC

Ich verwende aber auch in der Regel nur noch FireDAC, allein schon weil es in meiner Architect Edition dabei ist.

Nur in Ausnahmefällen muss ich mich an abweichende Kundenvorgaben halten.

Zitat:

Zitat von daddy (Beitrag 1537754)
Ich habe per Debugging im Delphi-Quellcode die Funktion "AddParamSQLForDetail" in der Unit "Data.DBCommon.Pas" als Ursache für das Problem herausgefunden, die einfach fehlerhaft arbeitet und offensichtlich nur mit einfach gestrickten Anweisungen der Art "Select * from <Table> order by <Column>" zurechtkommt. Weder Joins noch Unterselects werden in irgendeiner Form korrekt erkannt und berücksichtigt. Das in meinem obigen Beispiel von der Funktion eingefügte "where LNummer = ?" landet in diesen Fällen an der falschen Stelle und führt somit zu einer ungültigen Select-Anweisung.

Gibt es dafür einen Bugreport? Falls nicht: https://qp.embarcadero.com/

himitsu 14. Jun 2024 14:04

AW: DELPHI-Fehler in Master/Detail-Verknüfungem über MasterFields
 
privat nur 'ne Pro.
da fehlt leider auch Linux und iProdukte hab'sch net.

daddy 14. Jun 2024 16:03

AW: DELPHI-Fehler in Master/Detail-Verknüfungem über MasterFields
 
@ Sinspin
Mir ist natürlich klar, dass ich das Problem durch Änderungen in der Programmierung lösen kann. Es handelt sich aber um ein sehr umfangreiches Projekt und ich würde sehr viel Arbeit damit haben, alle Beziehungen dieser Art zu ändern. Ich bin einfach sehr überrascht, dass ein solch grober Fehler auch nach fast 20 Jahren noch in Delphi enthalten ist. Bin ich der Einzige der mit der genannten Konstellation von Komponenten arbeitet und Master/Detail-Beziehungen wie ursprünglich von Delphi vorgesehen nutzt?

@ Uwe Raabe
Ja, ich werde das mal an Embarcadero weitergeben. Das wird vermutlich nur keine schnelle Lösung für mein aktuelles Problem bringen.

Uwe Raabe 14. Jun 2024 16:25

AW: DELPHI-Fehler in Master/Detail-Verknüfungem über MasterFields
 
Zitat:

Zitat von daddy (Beitrag 1537768)
Ich bin einfach sehr überrascht, dass ein solch grober Fehler auch nach fast 20 Jahren noch in Delphi enthalten ist.

Wenn das niemand gemeldet hat...

Frickler 14. Jun 2024 17:01

AW: DELPHI-Fehler in Master/Detail-Verknüfungem über MasterFields
 
Mittels Views könntest Du komplexe Selektionen vereinfachen.
Code:
Create Or Alter View Name1 As Select L.*, K.Bezeichnung from LieferantKontakt left join KontaktArt K on L.KANummer = K.Nummer
und
Code:
Create Or Alter View Name2 As Select L.*, (Select K.Bezeichnung from KontaktArt where Nummer = L.KANummer) as Bezeichnung from LieferantKontakt
und dann hast Du wieder die ganz einfachen Anweisungen
Code:
Select * From Name1
und
Code:
Select * from Name2
.

Uwe Raabe 14. Jun 2024 17:56

AW: DELPHI-Fehler in Master/Detail-Verknüfungem über MasterFields
 
Ich kenne jetzt zwar das genaue Problem nicht, aber bei Master-/Detail-Beziehungen geht es ja darum, ein Master-Dataset und ein Detail-DataSet zu haben, wobei letzteres alle Detail-Records zu dem jeweils aktuellen Master-Record enthält. Ich kann im Moment noch nicht sehen, wie da die Select-Anweisungen reinspielen.

Andererseits liegt der Fehler ja offenbar innerhalb der Funktion AddParamSQLForDetail, in der eine SQL-Anweisung geparst und ergänzt wird. Da der Parser relativ simpel gestrickt ist (wobei das schon eine Wissenschaft für sich ist), kann ich mir schon vorstellen, dass der nicht für komplexe SQLs funktioniert. Umso wichtiger ist eben, die entsprechenden Fehlerfälle zu melden. Andernfalls wird das nämlich nie behoben.

himitsu 14. Jun 2024 18:02

AW: DELPHI-Fehler in Master/Detail-Verknüfungem über MasterFields
 
Vielleicht bei automatischer Verknubbelung der DataSets?

Weiß jetzt nicht wie FireDAC arbeitet, aber bei pgDAC gibt es mehrere Modi.

* man gibt das/die Field(s) des Masters an und das/die Field(s) des Details ... das WHERE wird automatisch gebaut und angehängt
* man gibt das/die Field(s) des Masters an und das/die Param(s) des Details ... das WHERE ist manuell ins SELECT eingebaut

und noch etwas für Grids (DevExpress oder so) mit eingebettetem SubGrid (je Datenzeile)
* man gibt das/die Field(s) des Masters an und das/die Field(s) des Details ... die Details sind ALLE geladen und werden per Filter zur Laufzeit gesucht
so ist es möglich bei allen/mehreren Masterzeilen je ein SubGrid einzublenden (gleichzeitig)

Sinspin 14. Jun 2024 19:31

AW: DELPHI-Fehler in Master/Detail-Verknüfungem über MasterFields
 
Zitat:

Zitat von daddy (Beitrag 1537768)
@ Sinspin
Mir ist natürlich klar, dass ich das Problem durch Änderungen in der Programmierung lösen kann. Es handelt sich aber um ein sehr umfangreiches Projekt und ich würde sehr viel Arbeit damit haben, alle Beziehungen dieser Art zu ändern. Ich bin einfach sehr überrascht, dass ein solch grober Fehler auch nach fast 20 Jahren noch in Delphi enthalten ist. Bin ich der Einzige der mit der genannten Konstellation von Komponenten arbeitet und Master/Detail-Beziehungen wie ursprünglich von Delphi vorgesehen nutzt?

Vermutlich weil das niemand so macht. Außer eventuell bei ganz einfachen Sachen.
Ich finde deine Methode erhlich gesagt faul.
Alle unsere Scripte müssen so gebaut sein das aus dem Script ersichtlich was mit wem zusammen hängt. Und zwar ohne das ich erst in der Komponente rumwühlen muss.
Ich rede auch nicht von einem Spielzeug Projekt. Das sind mehr als 600K eigene LOC mit mehr als 200 Dialogen.

Sinspin 14. Jun 2024 19:38

AW: DELPHI-Fehler in Master/Detail-Verknüfungem über MasterFields
 
Zitat:

Zitat von himitsu (Beitrag 1537777)
Weiß jetzt nicht wie FireDAC arbeitet, aber bei pgDAC gibt es mehrere Modi.

* man gibt das/die Field(s) des Masters an und das/die Field(s) des Details ... das WHERE wird automatisch gebaut und angehängt
* man gibt das/die Field(s) des Masters an und das/die Param(s) des Details ... das WHERE ist manuell ins SELECT eingebaut

FireDAC kann auch Param(s) auto create. Solange der Master offen ist wenn man das Detail aufmacht. Also einfach das Script schreiben, MasterSource setzen. MasterFields eintragen, Details kann man leer lassen, und los geht es. Absolut simpel.

Uwe Raabe 14. Jun 2024 22:18

AW: DELPHI-Fehler in Master/Detail-Verknüfungem über MasterFields
 
FireDAC ist da ziemlich flexibel: Master-Detail Relationship (M/D)

Wichtig dabei ist dieser Abschnitt:
Zitat:

So how does it work? FireDAC builds for qOrderDetails a list of pairs - qOrders fields and qOrderDetails parameters. Elements in each pair:

When MasterFields is not specified, then they have the same name;
Otherwise, the pair elements have the same position, the same fields in the MasterFields list, and the same parameters in the Params collection.
When the current qOrders record is changed, FireDAC assigns for each parameter a corresponding field value. In our case, qOrderDetails :OrderID parameter gets the qOrder OrderID field value. After that, the qOrders is reexecuted.

MichaelT 17. Jun 2024 09:11

AW: DELPHI-Fehler in Master/Detail-Verknüfungem über MasterFields
 
Howdy!

Gib ein Request an QC auf und fixe das Ding wie damals an zentraler Stelle.

--

Einer der Gründe für den Multi-Tier Approach bei DB Anwendungen und das Briefcase Model waren die Kosten beim Erzeugen einer Datenbank Session. Verkauft wurde damals, was war noch vor Zeiten performanter Internetverbindungen und Enterprise Web in der Breite. Hernach blieb noch das Brief Case Model und der Export von Daten als XML Datei, das war modern. Die Java Stacks kannten keine Middleware und sendeten Daten als XML Stream übers Netz.

Es spielt noch rein, dass Access einen Write Through über ODBC auf zumindest Oracle (indirekt auch über Views) und SQL Server auf Master Detail Beziehung konnte bewerkstelligen. Der Einfluss der BDE, damals waren die Zahl der Datentypen noch sehr überschaubar und diese waren eher primitiv (nicht komplex), ist auch ein wenig noch zu spüren.

Der Client Dataset gehört mehr oder minder zu Midas und war eine in C/C++ implementierte Library welche verteilt werden musste und in 32-bit exklusiv vorlag und Quellcode, so ich mich recht erinnere, war nicht verfügbar. Deswegen scheuten die Delphi Progammierer den Zugang. Ich hoffe ich irre mich diesbezüglich nicht. Später wurde die Library in Pascal neu geschrieben usw...

Der Client Dataset kann heute viel und dessen Einsatz wurde beliebter, da Gruppierung und Aggregate lokal einfach per Definition gebildet werden können. Seit einer Präsentation vom David I. (vermutlich als Moderator) und dem Buch vom Cary Jenson sehe ich den Client Dataset anders und bin fast schon ein Fan. Naja, sagen wir einmal so.

Sowohl AnyDAC/FireDAC als auch die Komponenten von CoreLab/Devart entstanden hernach und insbesondere FireDAC löst das Thema anderes bspw. über den Einsatz von Commands. Bei FireDAC ist der Comp Layer ein Überbau in der obersten Schicht.

Der Dmitri A. verweis mich stolz wie Oskar auf das Demo mit den Commands und der Fähigkeit No Code ähnlich gelagerte Problemstellungen auf der Dataset Ebene zu lösen und ich dachte mir, 'Liab. Ist für die Weiber. Wer braucht so etwas?'. Wesentlich ist, Third-Party Komponenten sind mit solcher einer in Intention 'in mind' designed und eher von Grund auf. Das Datenbankdesign in die Richtung zu verbiegen, das wird es bei dir vermutlich schon gar nicht spielen.

Der Fluch dieser TDataSet Abstraktion ist einfach, dass diese gemeinsame Schicht zwar technisch Datenbanken abstrahiert, aber ADO & Co und die Multi-Tier DB Architecture (MTS, COM+) mehr mit der mangelnden Performance des MS-SQL Server zu tun hatte. Der fetzt erst seit der Version 2005 und später, zuvor wurde soviel pessimistisch gesperrt, dass der Sau grauste, selbst noch unter 7.

Welche DB Client library nimmst du? Historisch bieten sich DBX und teils ADO im Zusammenhang mit dem ClientDataSet an? Aber ich vermute du wirst den Patch lassen müssen.

lg.
Hoppy





Zitat:

Zitat von daddy (Beitrag 1537754)
Ich bin dabei ein Projekt von Delphi 7 auf Delphi 11 zu migrieren und habe ein Problem, das ich damals durch einen eigenen Eingriff in die Delphi-Quellcodes gelöst habe, das aber überraschenderweise auch in Delphi 11 immer noch besteht.

Es geht um eine VCL-Anwendung mit Firebird-Anbindung. Der Zugriff auf Firebird erfolgt über TClientDataSets, die über TDataSetProvider mit TSQLDataSets kommunizieren. An vielen Stellen werden Master-Detail-Verknüpfungen benötigt. Diese werden bereitgestellt, indem im TClientDataSet der Detailtabelle die Eigenschaften "MasterSource", "MasterFields" und "IndexFieldNames" gefüllt sind. Bei einfachen SQL-Selects funktioniert das auch:

Beispiel Master:
Delphi-Quellcode:
Select * from Liefeant

Beispiel Detail:
Delphi-Quellcode:
Select * from LieferantKontakt


Die Tabelle Lieferant hat ein Feld "Nummer", die Tabelle Kontakt ein Feld "LNummer", das sich auf das Feld Nummer bezieht. Mein Programm verhält sich genauso wie gewünscht.

Meistens sind die Detailtabellen aber ein wenig komplexer aufgebaut und stellen auch Daten anderer Tabellen bereit. Und dies führt zwangsläufig zu Fehlermeldungen von Delphi, egal ob Version 7 oder 11.
Hier einfache Beispiele für nicht funktionierende Abfragen, bei denen zur Tabelle LieferantKontakt noch ein Bezeichner aus einer Tabelle KontakArt geholt wird:
Detail:
Delphi-Quellcode:
Select L.*, K.Bezeichnung from LieferantKontakt left join KontaktArt K on L.KANummer = K.Nummer

oder
Delphi-Quellcode:
Select L.*, (Select K.Bezeichnung from KontaktArt where Nummer = L.KANummer) as Bezeichnung from LieferantKontakt


Ich habe per Debugging im Delphi-Quellcode die Funktion "AddParamSQLForDetail" in der Unit "Data.DBCommon.Pas" als Ursache für das Problem herausgefunden, die einfach fehlerhaft arbeitet und offensichtlich nur mit einfach gestrickten Anweisungen der Art "Select * from <Table> order by <Column>" zurechtkommt. Weder Joins noch Unterselects werden in irgendeiner Form korrekt erkannt und berücksichtigt. Das in meinem obigen Beispiel von der Funktion eingefügte "where LNummer = ?" landet in diesen Fällen an der falschen Stelle und führt somit zu einer ungültigen Select-Anweisung.
Natürlich könnte ich das Problem irgendwie umschiffen oder wieder - wie damals bei Delphi 7 - den delphieigenen Code korrigieren. Aber das erste macht mir aufgrund des Projektumfangs ziemlich viel Aufwand und das zweite zwingt mich bei jedem Delphi-Update die Korrekturen erneut vorzunehmen.

Kennt irgend jemand von euch (oder von Embarcadero) dieses Problem und hat evtl. eine bessere Lösung?



Alle Zeitangaben in WEZ +1. Es ist jetzt 09:02 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz