Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi frage zum clientdataset (https://www.delphipraxis.net/123604-frage-zum-clientdataset.html)

hyype 5. Nov 2008 09:18

Datenbank: MySQL • Zugriff über: ADO

frage zum clientdataset
 
hiho

Ich habe mich mal hier angemeldet, weil ich mich z.z. mit Delphi im Zusammenhang mit sql-Datenbanken beschäftige und diesbezüglich noch sehr wenig Ahnung habe.
Z.Z. schlag ich mich mit dem Steuerelement ClientDataSet (CDS) rum:
Wenn ich dieses doppelt anklicke, kann ich ein neues Feld hinzufügen. Dies habe ich getan. Mein Feld heißt KENNUNG, die Daten sind vom Typ String und maximal 20 Zeichen lang, funktioniert auch wunderbar.
Nun wollte ich dieses Feld im Quellcode definieren und habe dafür 2 Möglichkeiten ergoogelt:
1.)
datamodule3.ClientDataSet1.FieldDefs.Clear;
datamodule3.clientdataset1.FieldDefs.add('KENNUNG' ,ftString,20);
2.)
with datamodule3.clientdataset1.FieldDefs do
begin
clear;
with addfielddef do
begin
name:='KENNUNG';
datatype:=ftString;
size:=20;
end;
end;

Ich habe mir eine kleine Procedure namens def_feld geschrieben, in der ich beide Varianten ausprobiert habe (natürlich nicht zeitgleich, sondern immer eine auskommentiert).
diese habe ich nun in meiner eigentlichen Procedure an allen möglichen Stellen eingefügt:

clientdataset1.CreateDataSet;
clientdataset1.close;
clientdataset1.open;

vor CreateDataSet, vor Close, vor Open, nach Open
und ganz am Anfang vom Programm, wo's noch gar nicht um das CDS geht sowie ganz am Ende, wo der Teil mit dem CDS längst abgeschlossen ist, also sprich: wirklich überall.
Das Ergebnis war immer das gleiche: Es hat nicht funktioniert.
Daher jetzt meine Frage:
Wie kann ich im Quellcode das realisieren, was ich per Hand problemlos machen konnte, nämlich statt der gesamten Tabelle nur die Spalte KENNUNG anzeigen???

Vielen Dank für eure Hilfe schonmal.

Und falls ihr einen guten Link zu nem Crashkurs in Datenbankenprogrammierung mit Delphi (ADO) habt, immer her damit! ;)

mfg

Frank

hyype 6. Nov 2008 07:01

Re: frage zum clientdataset
 
weiß es keiner? :/

edit:
ich habe jetzt möglichkeit 2 favorisiert und noch etwas hinzugefügt
das ganze sieht jetzt so aus:

clientdataset1.active:=false;
datamodule3.ClientDataSet1.FieldDefs.Clear;
datamodule3.ClientDataSet1.IndexDefs.Clear;
with datamodule3.clientdataset1 do
begin
with FieldDefs.addfielddef do
begin
datatype:=ftString;
size:=20;
name:='KENNUNG';
end;
with IndexDefs.AddIndexDef do
begin
Fields := 'KENNUNG';
Name := 'IntIndex';
end;
end;
clientdataset1.CreateDataSet;
clientdataset1.close;
clientdataset1.open;

Das sieht jetzt exakt so aus wie in der Hilfe, jedoch gibt er mir nach wie vor die ganze Tabelle aus statt nur der Spalte KENNUNG.
Heut ist der 3. Tag, an dem ich mich damit rumschlag, also wenn einer helfen kann... wäre toll...

nahpets 6. Nov 2008 09:07

Re: frage zum clientdataset
 
Hallo,

kann Dir Deine Frage nicht beantworten, aber schau mal hier

Eventuell: http://www.delphipraxis.net/internal...ct.php?t=60592
oder auch: http://forum.delphi-treff.de/showthread.php?t=10651
oder: http://www.delphi-forum.de/viewtopic.php?p=531596

Was passiert denn, wenn Du Close und/oder Open weglässt?
Delphi-Quellcode:
ADODataSet1.CreateDataSet;
ADODataSet1.Close;
ADODataSet1.Open;
Bei der Reihenfolge bekomme ich eine Fehlermeldung, dass der Connectionstring fehlt, klar, habe auch keinen vergeben.
Delphi-Quellcode:
ADODataSet1.CreateDataSet;
ADODataSet1.Open;
So bekomme ich eine leere Datenmenge mit der Spalte Kennung. Auch klar, habe ja keine Daten hinzugefügt.

Daraus schließe ich jetzt mal (vorschnell):
Fielddef sorgt für die Tabellendefinition.
CreateDataSet erstellt den Dataset.
Close schließt ihn.
Open erstellt ihn neu mit den Inhalten aus dem Connectionstring und CommandType sowie CommandText, so dass Deine "manuelle" Vorarbeit hier wieder verloren geht.

Schau bitte mal nach der Beschreibung in der Hilfe (d7dbd.hlp) zu TADODataSet verwenden. Eventuell kommst Du damit weiter.

hyype 6. Nov 2008 09:45

Re: frage zum clientdataset
 
yippieh, ein Poster :)
Also, wenn ich die CDS-Komponente auf meinem Datenmodulformular doppelt anklicke und ein neues Feld hinzufüge mit den Parametern
name = KENNUNG
typ = String
size = 20
fügt er im Quellcode bei type TDataModule3 usw ein TStringField namens ClientDataSet1KENNUNG hinzu.

type
TDataModule3 = class(TDataModule)
ADOConnection1: TADOConnection;
ADOQuery1: TADOQuery;
DataSource1: TDataSource;
ClientDataSet1: TClientDataSet;
DataSetProvider1: TDataSetProvider;
ClientDataSet1KENNUNG: TStringField; <- per Doppelklick aufs CDS erstellt

Die Eigenschaften fielddefs und indexdefs des CDS bleiben dagegen unverändert leer.
D.h. unter Umständen macht mein Code gar nicht das, was ich dachte, was er machen würde.
Evtl benutzt man fielddefs um manuell eine Tabelle zu erstellen, das ist ja nciht das, was ich will, ich hole mir ja die Tabelle aus ner SQL-DB, will von den Spalten aber z.z. nur eine anzeigen (könnte man auch in der SQL-Anweisung formulieren, aber das ist hier nicht das Ziel)
Ich versuche jetzt gerade, irgendwie zur Laufzeit dem DataModule3 diese TStringField-Komponente hinzuzufügen.
Was mich dabei blos wundert, ist, dass diese Komponente scheinbar nirgends in Verbindung mit dem CDS zu stehen scheint, also weder ist bei dem StringField ein Verweis auf das CDS eingetragen, noch ist beim CDS ne Verlinkung auf das StringField. Lediglich der Name deutet darauf hin, dass die was miteinander zu tun haben.
Darüber hinaus kann ich aus der mainunit mit Datamodule3. das CDS ansteuern, nicht aber dieses TStringfield, das versteh ich leider auch nicht.

zum open bzw close weglassen:
Lass ich close weg, füllt sich mein DBGrid nicht mit Daten sondern nur mit den Spaltenbezeichnungen, lass ich open weg bleibt mein DBGrid leer.

edit:
Ich habe dem DataModule3 jetzt ein TStringField-Komponente mit der Bezeichnung ClientDataSet1KENNUNG hinzugefügt und alle Eigenschaften des händisch erstellten StringFields (welches ich anschließend natürlich gelöscht habe) übernommen. Ein Klon sozusagen. Dieser ist jedoch nicht lebensfähig, soll heißen, das Programm checkt nich, dass der was mit dem CDS zu tun hat (hätte mich auch gewundert, wenn's so einfach wäre). Ich gehe daher davon aus, dass es zwischen dem StringField und dem CDS schon eine Verbindung gibt, diese mir aber über den Objectinspector bzw die Eigenschaften des CDS bzw des StringFields nicht einsehbar ist.

Die Frage bleibt wie folgt:
Wie kriege ich es mit Quellcode realisiert, dass das CDS mir statt aller enthaltenen Spalten nur eine anzeigt???
Ich bin mit meinem Latein jedenfalls am Ende, werde noch ein wenig rumgoogeln und auf DEINE Hilfe hoffen. ;)

hyype 6. Nov 2008 14:53

Re: frage zum clientdataset
 
kann es sein, dass das, was ich machen will, gar nicht möglich ist?
meiner letzten recherche zufolge kann ich zur design-time den felder-editor öffnen und ein persistentes feld eintragen, welches bestehen bleibt, auch wenn sich die datenstruktur ändert (das ist das, was ich gemacht habe)
zur run-time kann ich wohl nur dynamische felder erzeugen
ich fand den gedanken ziemlich praktisch, eine tabelle in ihrer gesamtheit aus der db rauszuholen und dann erst eine einschränkung zu implementieren, welche daten ich dem user zugänglich mache und welche nicht
natürlich könnte ich jetzt ein neues cds erstellen und in dieses dann nur bestimmte spalten des 1. reinhaun und das 2. dann anzeigen, aber das gefällt mir nicht, dann könnt ich meine anfrage ja gleich in der sql-anweisung beschränken
also ich find, wenn das wirklich nicht so geht, wie ich das wollte, ist das ziemlich schwach von delphi....
ich würde mich aber dennoch freuen, wenn sich hier mal leute zu wort melden würden, die sich schon länger mit diesen dingen befassen als ich, der ich mich grade mal seit 4 tagen damit beschäftige (ich denke da z.bsp. an DragonsLear ^^) - einfach damit ich gewissheit habe - danke (und sorry für kleinschreibung)

nahpets 6. Nov 2008 15:20

Re: frage zum clientdataset
 
Hallo,

sorry, ist das schwach von Delphi oder eventuell von der benutzten Datenbankschnittstelle.
Habe ich an der von Dir "gefundenen" Baustelle noch nicht rumgetrieben, deshalb kann ich Dir da leider keine sinnvolle Hilfestellung anbieten.

hyype 7. Nov 2008 06:55

Re: frage zum clientdataset
 
wenn das so stimmt, wie ich es gefunden habe, dann bietet das cds zur entwurfszeit mehr möglichkeiten als zur laufzeit, also man kann händisch etwas tun, was mit quellcode nicht möglich ist, daher würde ich schon sagen, schwach von delphi

DeddyH 7. Nov 2008 08:16

Re: frage zum clientdataset
 
Zitat:

Zitat von hyype
dann bietet das cds zur entwurfszeit mehr möglichkeiten als zur laufzeit

Ich habe vom CDS zwar keine Ahnung, aber das kann ich mir beim besten Willen nicht vorstellen.

hyype 7. Nov 2008 10:40

Re: frage zum clientdataset
 
ich habs hier gefunden:
http://www.informit.com/articles/art...24094&seqNum=4
da steht, dass delphi ein persistentes feld objekt erzeugt, wenn man ein feld über den felder-editor erstellt
dieses ist eine komponente, die dem datenmodul hinzugefügt wird, aber laut objectinspector keinerlei Verbindung zum cds hat
außerdem kann man mit quellcode nicht darauf zugreifen. fielddefs bleibt dabei leer
zur laufzeit kann man über fielddefs "nur" dynamische felder erzeugen
hau dir einfach mal n cds auf dein form, klick doppelt drauf, erstell dir son feld und guck dir an, was er macht
dann versuch mal, das mit quellcode hinzubekommen
ich habe es nicht geschafft und nirgends gefunden, wie es gehen soll
d.h. natürlich nicht zwingend, dass es nicht möglich ist, aber es hat doch den anschein...

P.S.:
DragonsLear ist ja gar nicht hier sondern bei delphi-treff, werd mich da auch mal anmelden ^^

nahpets 7. Nov 2008 11:15

Re: frage zum clientdataset
 
Hallo,

sorry, aber meinst Du sowas?
Delphi-Quellcode:
procedure TForm1.Button3Click(Sender: TObject);
begin
  ADODataSet1.Open;
  ADODataSet1.Edit;
  ADODataSet1Spalte1.Value := '1111';
  ADODataSet1.Post;
  ADODataSet1.Close;
end;
Habe ein AdoDataSet auf's Form gepappt, 'nen Connectionstring zusammengebaut, CommandText = 'Tabelle', CommandType = cmdTable.
Doppelklick auf AdoDataSet, rechte Maustaste, Felder hinzufügen, okay.
Oben im Quelltext gibt es jetzt diese drei zusätzlichen Einträge
Delphi-Quellcode:
ADODataSet1Spalte1: TStringField;
ADODataSet1Spalte2: TStringField;
ADODataSet1Spalte3: TStringField;
und die kann man im Quelltext ansprechen.

Wie die Verbindung zwischen AdoDataSet und den Spalten hergestellt wird:
Delphi-Quellcode:
  object ADODataSet1: TADODataSet
    ConnectionString =
      'Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security In' +
      'fo=False;Initial Catalog=datenbänklie;Data Source=meinputer'
    CursorType = ctStatic
    CommandText = 'tabelle'
    CommandType = cmdTable
    Parameters = <>
    Left = 488
    Top = 288
    object ADODataSet1Spalte1: TStringField
      FieldName = 'Spalte1'
      Size = 10
    end
    object ADODataSet1Spalte2: TStringField
      FieldName = 'Spalte2'
      Size = 10
    end
    object ADODataSet1Spalte3: TStringField
      FieldName = 'Spalte3'
      Size = 10
    end
  end
Bin ich hier jetzt vollkommen auf dem falschen Dampfer :?:

hyype 7. Nov 2008 11:38

Re: frage zum clientdataset
 
das sieht dem was ich mitm ClientDataSet gemacht habe, schon sehr ähnlich
wo hast du den letzten Quellcode her, also wo in deinem Programm steht der drin? ^^
ich habe nirgends object drinne stehen ^^
kenn mich noch nicht wirklich gut aus, wie ich zugeben muss
hast du mal versucht, diese Spalten, die du ja auch mit dem Felder-Editor erstellt hast, per Quellcode zur Laufzeit zu erstellen?

edit:
ok, die .dfm im Editor angeguckt und schon seh ich auch solche Strukturen - wieder was gelernt ;)
aber wie realisiert man dieses nun mit Quellcode?

nochmal edit:
in dem andern Forum meinte jmd (der da Super-Moderator ist), dass man ein persistentes Feld nicht mittels Quelltext anlegen kann
damit hat sich das Thema dann wohl erledigt, vielen Dank an alle, die sich beteiligt haben

nahpets 7. Nov 2008 13:51

Re: frage zum clientdataset
 
Hallo,

und warum funktioniert das dann?
Delphi-Quellcode:
procedure TForm1.Button3Click(Sender: TObject);
Var
    ADODataSet1Spalte4 : TStringField;
begin
  ADODataSet1Spalte4 := TStringField.Create(ADODataSet1);
  ADODataSet1Spalte4.FieldName := 'Spalte4';
  ADODataSet1Spalte4.Size := 10;
  ADODataSet1Spalte4.DataSet := ADODataSet1;
  ADODataSet1.Open;
  ADODataSet1.Edit;
  ADODataSet1Spalte1.Value := '1111';
  ADODataSet1Spalte2.Value := '2222';
  ADODataSet1Spalte3.Value := '3333';
  ADODataSet1Spalte4.Value := '4444';
  ADODataSet1.Post;
  ADODataSet1.Close;
  ADODataSet1Spalte4.Free;
end;
Die ersten drei Spalten sind aus dem Beispiel von oben, die vierte wird hier zur Laufzeit dazugedaddelt.

hyype 10. Nov 2008 07:36

Re: frage zum clientdataset
 
Delphi-Quellcode:
procedure TForm2.def_feld();
var
  blub:TStringfield;
begin
  blub:=TStringfield.create(datamodule3.ClientDataSet1);
  with blub do
  begin
    Size:=11;
    FieldName:='KENNUNG';
    visible:=true;
    readonly:=false;
    displaylabel:='KENNUNG';
    autogeneratevalue:=arNone;
    displaywidth:=11;
    fieldkind:=fkData;
    fixedchar:=false;
    index:=0;
    lookupcache:=false;
    name:='ClientDataSet1KENNUNG';
    providerflags:=[pfinupdate,pfinwhere];
    required:=false;
    tag:=0;
    transliterate:=true;
    alignment:=taleftjustify;
  end;
  datamodule3.InsertComponent(blub);
end;
so hatte ich es letzte Woche auch versucht, hat nicht geklappt
habe jetzt mal noch
Delphi-Quellcode:
DataSet:=ClientDataSet1;
hinzugefügt und siehe da, es geht!! ES GEHT!!! ;)
(auch ohne insertcomponent ^^)
Vielen Dank nahpets!!!

hyype 12. Nov 2008 08:21

Re: frage zum clientdataset
 
Hi Leute!
Ich benutz den Thread hier nochmal für was anderes, was aber thematisch zum Threadnamen passt.
Und zwar versteh ich grad Sinn und Zweck vom CDS.Edit nicht...
Ich hab folgendes Konstrukt:
ADOConnection->ADOQuery->DSP->CDS->DS->DBGrid
wobei die ADO-Komponenten erstmal keine Rolle spielen.
Problem ist:
Ich möchte gern Änderungen im DBGrid vornehmen und per post ins CDS-File speichern. Dafür habe ich mir mehrere Buttons gemacht:
einen für insert bzw append (versteh den Unterschied nicht ganz da der mit insert eingefügte Datensatz beim speichern eh am Ende landet)
einen für edit (was laut Hilfe "das Bearbeiten des AKTIVEN DATENSATZES in der Datenmenge ermöglicht")
und einen für post

Und jetzt kommt das, was ich nicht verstehe:
Wenn ich die Daten im DBGrid änder und post klicke, speichert er alle Änderungen in mein CDS-File ohne dass ich jemals edit aufgerufen habe.
Und wenn ich die readonly-Eigenschaft des CDS auf true setze, kann ich auch im DBGrid nichts mehr ändern, da kann ich edit klicken wie ich will.
Ich habe mir das eigentlich so vorgestellt, dass ich zwar sämtliche Einträge im DBGrid ändern kann, bei post aber nur der aktive Datensatz gespeichert wird und auch nur, wenn vorher ein edit kam. Idealer wäre natürlich, dass Änderungen generell nur in der Zeile des aktiven Datensatzes möglich sind und auch nur nach einem edit, also wenn jmd weiß, wie man das umsetzen kann, zögere er nicht, es mir mitzuteilen! ;)
Ich werde natürlich selbst an dem Problem weiterarbeiten, evtl mal die Verbindung zwischen dem DBGrid und der DS "lösen" und erst vorm post wieder herstellen (mal gucken, ob das geht und was das bringt ^^)

ConstantGardener 12. Nov 2008 12:34

Re: frage zum clientdataset
 
Hallo hyype,

ich hab den Thread jetzt nicht ganz verfolgt aber hast Du in der DS AUTOEDIT auf true? Das sollte zumindest deine Verwunderung über das mögliche Post vor dem Edit erklären.

mfg cg

nahpets 12. Nov 2008 13:14

Re: frage zum clientdataset
 
Hallo,

schau mal in die Sourcen von DBGrids.pas von Delphi, da wird Edit automatisch aufgerufen, ich habe aber jetzt nicht analysiert, wann genau. Aber eventuell liegt es ja daran.

hyype 13. Nov 2008 08:51

Re: frage zum clientdataset
 
jo, autoedit der datasource war auf true
da die ganzen steuerlemente miteinander verknüpft sind, hat er dann änderungen im dbgrid automatisch übernommen und mit post gespeichert, ohne dass ich edit aufrufen musste
wenn ich dagegen im quellcode etwas verändern möchte, muss ich edit schon vorher aufrufen, damit es geht


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