AW: Kundenliste
Nochmal ganz langsam: egal, was Du mit Deiner eigenen Liste tust, Du musst es auch in der DB tun. Das bedeutet:
- Neuer Listeneintrag -> INSERT INTO Tabelle - Listeneintrag ändern -> UPDATE Tabelle - Listeneintrag löschen -> DELETE FROM Tabelle Ist doch eigentlich ganz einfach, man muss es nur tun. |
AW: Kundenliste
Wenn Du Recht hast, hast Du Recht. Aber ich vermute, daß der arme EdAdvokat Inhalt und Werkzeug nicht auseinander halten kann. Er wäre ja nicht der erste, dem das so geht.
@EdAdvokat Dir ist mehrere Male vorgeschlagen worden, daß Du Dir ein Konzept/Schlachtplan/PAP was auch immer, erarbeiten solltest, damit Du weißt welche Baustellen Du beackern musst und Du kannst überprüfen ob Dein Programm alles hat was es benötigt. Das Löschen von Datensätzen ist ja eigentlich kein Problem, wenn man den weiß welche. (Multiuserfähigkeit lassen wir mal außen vor) Debuggen lernt man so en passant, das ist nicht wirklich ein Thema, wenn man weiß wofür ein Debugger gut ist, und was er leisten kann. Also wenn Dir auffällt, daß Dein Programm etwas nicht kann/tut dann schau mal nach ob diese Fähigkeit auch in Deinem Entwurf enthalten ist. Wenn ja dann such diese Funktionalität in Deinem SourceCode, und falls Du dort etwas findest, dann überprüfst Du ob der Code korrekt ist. Gruß K-H |
AW: Kundenliste
Hallo EdAdvokat,
weil b) mMn wirklich die einfachste, weil am schnellsten umsetzbare Lösung ist zeige ich dir mal wie SaveToTB dafür zu ändern ist. Es ist nicht ideal oder effektiv, es ist nur damit es läuft. Das Vorgehen (auf dem Papier) ist dabei wie folgt: 1) Du lädst ja die Daten aus der DB in die CustomerList. Hast du schon. 2) Dann bearbeitest du die Daten in der CustomerList oder du fügst neue hinzu oder löschst welche. Hast du schon. 3) Jetzt soll gespeichert werden, d.h. der Stand in der CustomerList soll jetzt in die DB: Dazu: 3a) Lösche einfach den kompletten Inhalt der Tabelle in der DB. 3b) Füge nun alles in der CustomerList wieder in die DB. Beachte bei 3b) das nun nur noch Insert-Statements gebraucht werden (da die DB ja leer ist ist nichts upzudaten), aber es gibt Datensätze die bereits eine sinnvolle ID haben, die müssen mit einem anderen Statement Inserted werden
Delphi-Quellcode:
procedure TCustomerList.SavetoDB(con: TZConnection);
var zqryMain: TZQuery; i: Integer; begin zqryMain:=TZQuery.Create(nil); try zqryMain.connection:=con; //Erst mal alles löschen: zqryMain.SQL.Text:='Delete From WARENVERKAUF1'; // oder heißt es 'Delete * From WARENVERKAUF1'? zqryMain.ExecSQL; for I:= 0 to self.Count-1 do begin if self[i].ID>-1 then //Insert-Statement für bekannte Datensätze mit sinnvoller ID zqryMain.SQL.text:='INSERT INTO WARENVERKAUF1(ID,KDNR,NAME,VORNAME,FIRMA,PRODUKT,ANZAHL,PREIS) ' + 'VALUES(:CID, :KNR, :NAM, :VNA, :FIR, :PRO, :ANZ, :PRE)'; else //Insert Statement für wirklich neue Datensätze zqryMain.SQL.text:='INSERT INTO WARENVERKAUF1(KDNR,NAME,VORNAME,FIRMA,PRODUKT,ANZAHL,PREIS) '+ 'VALUES(:KNR, :NAM, :VNA, :FIR, :PRO, :ANZ, :PRE)'; zqryMain.params.parseSQL(zqryMain.sql.text, True); if self[i].ID>-1 then //Parameter ID wird nur in diesem Fall benötigt zqryMain.Params.ParamValues['CID']:=self[i].ID; //Restliche Parameter und ExecSQL wird eigentlich in beiden Fällen gleich benöigt //darum habe ich die Doppelung aus deinem Code mal rausgemacht (DRY). zqryMain.params.ParamValues['KNR']:=self[i].KDNR; zqryMain.params.paramValues['NAM']:=self[i].Name; zqryMain.params.paramValues['VNA']:=self[i].Vorname; zqryMain.params.ParamValues['FIR']:=self[i].Firma; zqryMain.Params.ParamValues['PRO']:=self[i].Produkt; zqryMain.Params.ParamValues['ANZ']:=self[i].Anzahl; zqryMain.params.paramValues['PRE']:=self[i].Preis; zqryMain.ExecSQL; end; finally zqryMain.Free; end; end; |
AW: Kundenliste
Ralf (Jumpy) ich bin sowas von glücklich, dass es jetzt mit deinem Codevorschlag genau so funktioniert, wie ich es mir vorgestellt habe. Er tut all das, was ich zurückliegend beschrieben habe, sogar ohne zu murren.
Gestatte mir bitte einige Fragen dazu: 1.) Das Löschen aller Datensätze mit
Delphi-Quellcode:
ist offensichtlich auf dem Desktop nicht sichtbar, da das Listview in dieser Phase nicht aktualisiert wird. Es bleiben alle Datensätze in der Tabelle und in der objectlist. Richtig?
zqryMain.SQL.Text:='Delete From WARENVERKAUF1';
zqryMain.ExecSQL; 2.) mit Zitat:
3. Insert für wirklich neue Datensätze ist die Möglichkeit, die mit hinzufügen für eine ID= -1 sorgen und nun neu aufgenommen werden und dabei zugleich eine ID der DB (also <> -1 erhalten. Richtig? 4.) was bedeutet:
Delphi-Quellcode:
Parameter ID wird nur in diesem Fall benötigt. Davor gab es doch diese if-Bedingung bereits auch?
if self[i].ID>-1 then //Parameter ID wird nur in diesem Fall benötigt
zqryMain.Params.ParamValues['CID']:=self[i].ID; 5.) Die procedure unterscheidet sich doch wesentlich von den Vorversionen, denn ein Update-Statement gibt es nun nicht nur Insert, da ja zunächst die DB völlig gelöscht wird, um dann "würdige Datensätze" und neue Datensätze aufzunehmen. Bearbeiten klappt auch, da auch in diesm Fall kein Update erforderlich ist, denn die Veränderung wird ja neu eingefügt. Das ist ja dialektisch!(3. dialektisches Grundgesetz Negation der Negation) Richtig in Bezug auf den programmtechnischen Inhalt? 6.) Wäre auch eine selektive Löschung des aktuellen Datensatzes über die Auswahl der ID= :CID möglich? Bedeutet dein Hinweis unter 3b dass die"würdigen Datensätze" trotz ID<> -1 eine völlig neue ID von der DB erhalten, die es zuvor nicht gab. Eigentlich logisch den sonst gäbe es ein Chaos. Ich danke Dir ganz ganz herzlich, denn so hat das Programm zunächst seinen Ende gefunden und ich gehe daran alles zu kommentieren und einzuprägen. Nochmals zu den grundsätzlichen Anmerkungen von K-H (p80286): Ich habe doch all das was Du angesprochen hast zuvor bereits formuliert, also ein "Pflichtenheft" erstellt, in dem ich dargelegt habe, was ich will und was das Programm soll und tun muss. Dann wurde Schritt für Schritt, mit Stolpern und Stürzen all das implementiert geprüft, verworfen und erneut eingefügt. Was hätte ich denn da noch darlegen sollen? Es geht darum, dass ich all das Schritt für Schritt auch so verstehe dass ich euren Hinweisen wirklich folgen kann. Nochmals Danke für Eure Bemühungen, verbunden mit der voran geäußerten Bitte nach Tutorial-Hinweisen und int. Links. (Delphi-Starter-Tutorial bitte nicht, denn das habe ich bereits studiert und Bücher, die nun gut 15 Jahre als sind mit Stand Delphi 4 bis 7 habe ich auch, doch darin sind derartige Probleme leider überhaupt nicht enthalten. |
AW: Kundenliste
Zu 1)
Es sind alle Datensätze in der ListView und in der CutomerList auf dem gleichen Stand. Es wird dann die komplette Tabelle in der DB geleert, d.h. darin sind keine Daten mehr, um dann im nächsten Schritt den kompletten Stand der CutomerList (so wie sie jetzt ist) in die DB zu schreiben. Zu 2) Genau. Die Datensätze, die bereits eine ID haben (ungleich -1) sollen ja auch mit dieser ID in die DB geschrieben werden, darum enthält das entsprechende Instert-Statement auch die ID und den Parameter :CID. Zu 3) Auch richtig. Hier hat der Datensatz noch keine ID (bzw. die ist ja -1). Daher wird beim Insert-Statement die ID weggelassen, wodurch die Datenbank automatisch eine ID vergibt. Zu 4) Hier habe ich nur versucht deinen Code zu verkürzen und Redundanz zu vermeiden. DRY (=Don't repeat yourself) ist so ein Programmierer Ding: aus:
Delphi-Quellcode:
wurde:
if self[i].ID>-1 then
begin zqryMain.Params.ParamValues['CID']:=self[i].ID; //update zqryMain.params.ParamValues['KNR']:=self[i].KDNR; zqryMain.params.paramValues['NAM']:=self[i].Name; zqryMain.params.paramValues['VNA']:=self[i].Vorname; zqryMain.params.ParamValues['FIR']:=self[i].Firma; zqryMain.Params.ParamValues['PRO']:=self[i].Produkt; zqryMain.Params.ParamValues['ANZ']:=self[i].Anzahl; zqryMain.params.paramValues['PRE']:=self[i].Preis; zqryMain.ExecSQL; end else begin zqryMain.params.ParamValues['KNR']:=self[i].KDNR; //insert zqryMain.params.paramValues['NAM']:=self[i].Name; zqryMain.params.paramValues['VNA']:=self[i].Vorname; zqryMain.params.ParamValues['FIR']:=self[i].Firma; zqryMain.Params.ParamValues['PRO']:=self[i].Produkt; zqryMain.Params.ParamValues['ANZ']:=self[i].Anzahl; zqryMain.params.paramValues['PRE']:=self[i].Preis; zqryMain.ExecSQL; end;
Delphi-Quellcode:
Ist doch viel kürzer, macht aber das selbe.
if self[i].ID>-1 then
zqryMain.Params.ParamValues['CID']:=self[i].ID; zqryMain.params.ParamValues['KNR']:=self[i].KDNR; zqryMain.params.paramValues['NAM']:=self[i].Name; zqryMain.params.paramValues['VNA']:=self[i].Vorname; zqryMain.params.ParamValues['FIR']:=self[i].Firma; zqryMain.Params.ParamValues['PRO']:=self[i].Produkt; zqryMain.Params.ParamValues['ANZ']:=self[i].Anzahl; zqryMain.params.paramValues['PRE']:=self[i].Preis; zqryMain.ExecSQL; Zu 5) Richtig verstanden. Zu 6) Zur Wiederholung: Würdige Datensätze :) die bereits eine ID haben behalten diese, nur Unwürdige oder besser bisher Unbekannte bekommen eine neue ID. Genau das passiert, wie unter Zu2) und Zu3) beschrieben. Grundsätzlich ist es natürlich auch möglich Datensätze über die ID selektiv zu löschen, aber dann muss man sich auch vorher merken, welche Datensätze das sind, und da hast du im jetzigen Stand deines Programmes keine Struktur für vorgesehen. Schau dir nochmal in #64 meinen Vorschlag d) an. Da musst du dir mal gut überlegen (auf'm Papier) was man dazu machen müsste um das umzusetzen und wo man alles was ändern müsste. Das ist eigentlich gar nicht so viel und du solltest das schaffen können. Es würde dein Programm in der Performance - gerade beim Speichern - um einiges verbessern. |
AW: Kundenliste
Danke Ralf (Jumpy). All das hat bei mir doch eine ganze Menge Licht ins Dunkele gebracht, einschließlich DRY:), das kannte ich nicht und wollte aber nicht fragen. Ich habe Dein Statement verstanden. Auch glaube ich den von Dir angesprochenen Punkt d) aus #64 jetzt zu verstehen ohne dabei ins Detail zu gehen, denn das will ich erst einmal ganz allein für mich probieren.
Auch Punkt a) sehe ich jetzt etwas anders. Beim ButtonClick auf löschen den DS in der customerlist und danach auch in der DB selektiv löschen dann fülleListview und weg ist er. Das selektive Löschen mit SQL-Statement ala 'Delete * form Warenverkauf1 WHERE ID= :CID' zu c) Will ich mal mein Verständnis darlegen: eine zweite Liste innerhalb der CustomerList einfügen statt Add Datensatz den zu löschenden Datensatz darin markieren, um ihn dann gesondert zu löschen. Dazu jedoch die alte Fassung von SaveToDB (die das löschen nicht ermöglicht hat) und dann für die in der gesonderten Liste aufgeführten Datensätze ein Delete-Statement einfügen und weg damit aus der objectlist und dann auch aus der DB. Habe ich das so richtig verstanden? Ich will mal so kühn sein und behaupten, ich habe #64 jetzt verstanden. (vorher war mir so, als würde jemand von mir verlangen, ich sollte japanische Verben konjuniern) Ich werde also studieren und probieren. Ich wäre dir für eine kurze Antwort, ob ich prinzipiell richtig liege dankbar. |
AW: Kundenliste
Punkt a) hast du glaub ich verstanden wie ich das meinte. Punkt c) Ansatzweise, drum erkläre ich den mal einfacher.
Stell dir vor in der Klasse CustomerList, die ja eine Objektlist beinhaltet, hast du noch eine weiter Liste enthalten, dass könnte z.B. nur eine einfache TStringlist sein. Wenn du jetzt einen Datensatz Deletest in der CustomerList, gehst du erst hin und schreibst die ID des Datensatzes in die StringList, denn die ID ist ja alles, was du später zum löschen brauchst. Dann löschst du den Datensatz/Customer aus der CustomerList und füllst die ListView neu. Beim SaveToDB benutzt du dann die Funktion die du am Anfang hattest (ohne DRY :-D) mit dem Insert und Update. Anschließend gehst du dann noch die Stringliste durch und setzt für jede darin gespeicherte ID noch ein passendes DeleteStatement ab. |
AW: Kundenliste
Ralf, in #44 hast Du geschrieben:
Zitat:
|
AW: Kundenliste
Das sollt ungefähr so sein:
Delphi-Quellcode:
Das ist nur das Prinzip!
type
TMyList : Class(Tobjectlist); procedure Delete(idx:integer); end; procedure TMylist.Delete(idx:integer); { lÖSCHEN DES DATENSATZES AUS DER lISTE } begin if self.id>-1 then DeleteFromDB(self.id); { und aus der DB } inherited dELETE; end; die genaue Umsetzung ist dann Dein Problem:wink: Gruß K-H |
AW: Kundenliste
Es müsste glaub ich
Delphi-Quellcode:
sein, aber im Prinzip hat p80286 recht. Genauso hast du ja z.B. die Add oder Remove Funktion überschrieben, wenn ich deine CutomerList gerade richtig im Kopf hab.
if self[idx].id>-1 then DeleteFromDB(self[idx].id);
inherited Delete(idx); Deine Aufgabe wäre dann natürlich noch die Prozedur DeleteFromDB(ID:String) oder so ähnlich zu schreiben. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:53 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz