Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   ClientDataSet übernimmt Wert nicht (https://www.delphipraxis.net/194553-clientdataset-uebernimmt-wert-nicht.html)

EricMeyer 6. Dez 2017 18:31

Datenbank: MySql • Version: 5.7.19 • Zugriff über: ka

ClientDataSet übernimmt Wert nicht
 
Ich habe ein DBGrid von Devexpress und dadrin ein paar Daten. Ich möchte jetzt zu diesen Daten eine weitere Zeile hinzufügen. Soweit nichts besonderes.
Nun habe ich ein ganz ungewöhnliches Verhalten. Das Feld 'bezeichnung' ist vom Typ widestring. Ich versuche diesem einen Wert zuzuordnen. Aber der Wert von cbbezeichnung.EditText wird nicht übergeben. Im Debugger sieht man, dass im cbbezeichnung.edittext ein Wert vorhanden ist, aber FCds.FieldByName('bezeichnung').Value bleibt bei "" stehen.


Delphi-Quellcode:
 
{FCds = TClientDataSet}
FCds.Append;
FCds.FieldByName('bezeichnung').Value    := cbbezeichnung.EditText;
FCds.FieldByName('von').AsDateTime       := dateedtVon.Date;
FCds.FieldByName('id').AsFloat           := id;
FCds.Post;
Alternativ habe ich versucht:
Delphi-Quellcode:
FCds.FieldByName('bezeichnung').asWideString := cbbezeichnung.EditText;
mit dem selben Ergebnis
Delphi-Quellcode:
FCds.FieldByName('bezeichnung').asWideString := null;
dieses führt dazu, dass anschließend Null in FCds.FieldByName('bezeichnung').asWideString steht. Somit ist zumindest das Feld veränderbar.

In der UniQuery Komponente habe ich RequiredFields und SetFieldsReadOnly auf False gesetzt.

Ich habe schon einmal fast alles gelöscht und neu gemacht. Mir gehen die Ideen aus.

himitsu 6. Dez 2017 18:57

AW: ClientDataSet übernimmt Wert nicht
 
AsWideString brauchst du nicht, da du sowieso nur Strings rein gibst. (cbbezeichnung.EditText ist ein String)
Delphi-Quellcode:
FCds.FieldByName('bezeichnung').AsString := cbbezeichnung.EditText;


Wie bei
Delphi-Quellcode:
FCds.FieldByName('bezeichnung').asWideString := null;
der Text
Delphi-Quellcode:
'Null'
rein kommt, ist mir ein Rätsel.
Null zu String umgewandelt ergibt eigentlich eine Exception. :gruebel: (außer bei Delphi-Referenz durchsuchenVarToStr, wo dann
Delphi-Quellcode:
''
raus kommt)
Delphi-Quellcode:
FCds.FieldByName('bezeichnung').Value := Null;
, aber aufpassen, denn das geht nur bei TField als Typ, da hier die Ableitungen bösartig/fahrlässig dieses Property verdecken (bei TStringField ist Value=String anstatt Variant),
oder
Delphi-Quellcode:
FCds.FieldByName('bezeichnung').AsVariant := Null;
,
aber besser gleich so
Delphi-Quellcode:
FCds.FieldByName('bezeichnung').Clear;



Ist FCds.FieldByName('bezeichnung').Value / .AsString vor dem Post mit dem neuen Wert gefüllt,
oder ist er erst nach dem Post weg?


ClientDataSet oder UniQuery?
Gibt es da ein SELECT-Statement oder sowas, und wenn ja, wie ist dort "bezeichnung" definiert?

EricMeyer 6. Dez 2017 19:11

AW: ClientDataSet übernimmt Wert nicht
 
sorry ja es ist natürlich:
Delphi-Quellcode:
  FCds.FieldByName('bezeichnung').Value := null;
Das Statement ist aber nur zum Testen gewesen und wird nicht wirklich benötigt.

Das select statement ist absolut standard nach dem motto select a.a, a.b, b.c from abc as a join bcd as b on (b.id = a.bid)

das Feld bezeichung ist ein varchar(20) Feld.

Wenn ich dem Feld im Clientdataset die Eigenschaft String statt WideString zuordne, wird mir beim FCds.open, also dem Öffnen des Clietdataset ein Fehler ausgeworfen, dass des Feld String ist, aber Widestring benötigt.


Zitat:

Ist FCds.FieldByName('bezeichnung').Value / .AsString vor dem Post mit dem neuen Wert gefüllt,
oder ist er erst nach dem Post weg?
Ist direkt leer, schon vor dem Post. Das ist ja das seltsame daran.

himitsu 6. Dez 2017 22:02

AW: ClientDataSet übernimmt Wert nicht
 
Zitat:

Das select statement ist absolut standard nach dem motto select a.a, a.b, b.c from abc as a join bcd as b on (b.id = a.bid)
Standard gut und schön.
Wie steckt da "bezeichnung" nur drin?

Berechnete Felder und angejointe Felder werden standardmäßig nicht zurückgeschrieben.
Nur die Felder, welche erkannt werden, dass sie aus der UpdatingTable (normalerweise die vom FROM) stammen.
Das bezieht sich auf das Zurückschreiben über das automatisch erstellte UpdateSQL-Statement. (du kannst dieses auch selber schreiben und dann machen was du willst)

Wenn du dir also über die Log-Funktion der Connection das Update-Statement ausgeben lässt, dann tauchen solche Felder dort nicht auf und der Feldinhalt verschwindet ins Nichts.

EricMeyer 7. Dez 2017 00:03

AW: ClientDataSet übernimmt Wert nicht
 
Okay, also bezeichnung ist ein und zwar das einzige gejointe Feld! Das es daran liegt, darauf wäre ich nie gekommen! Danke schon mal so weit. Aber wie löse ich jetzt das Problem?
Also ich möchte einfach nur, dass in der Spalte Bezeichnung etwas angezeigt wird. Später zum speichern benötige ich die Zeile nicht, da verwende ich die zugehörige ID, die ich auch übergebe.

EricMeyer 7. Dez 2017 11:59

AW: ClientDataSet übernimmt Wert nicht
 
Okay, ich habe mein Problem gelöst.
bezeichnung ist abhängig von bezeichnungsid. Diese ID ist direkt in der "UpdatingTable"-Tabelle. Ich habe also ein neues Feld hinzugefügt, das die Eigenschaft Berechnet hat, als String, (wichtig nicht vergessen, die Feldgröße einzustellen) und mache in CalcFields des Clientdataset eine neue SQL-Abfrage, mit der ich aus der bezeichnungsid die Bezeichnung mache und füge diese hinzu.
Ist leider jetzt eine Abfrage für jede Zeile, aber Die DB-Tabelle hat nur vier Einträge und die Tabelle Grid kommt auf maximal 100 denke ich. Also ist das okay.

Vorher hatte ich es noch versucht, indem ich eine temporäre Tabelle im SQL erstelle, in der Hoffnung, dass er dann den ganzen Select als eine UpdatingTable erkennt, das hat aber nicht funktioniert.

himitsu 7. Dez 2017 13:44

AW: ClientDataSet übernimmt Wert nicht
 
Wie gesagt, meistens gibt man nur das SELECT-Statement (.Sql) an
und lässt sich die anderen Statements (INSERT, UPDATE und DELETE) automatisch generieren.

Man kann hier aber auch eigene SQL-Skripte angeben.
SQL-Code:
-- Sql:
SELECT x.a, x.b, z.c FROM x JOIN z ON z.a = x.a;

-- SqlUpdate:
UPDATE x SET a = :a, b = :b WHERE a = :old_a;
UPDATE z SET a = :a, c = :c WHERE a = :old_a;

-- SqlDelete:
DELETE FROM x WHERE a = :old_a;
DELETE FROM z WHERE a = :old_a;

...
z.B. siehe https://www.devart.com/unidac/docs/?....sqlupdate.htm


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:33 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