Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi TClientDataSet: AutoInc auch wirklich automatisch inc-en (https://www.delphipraxis.net/83372-tclientdataset-autoinc-auch-wirklich-automatisch-inc-en.html)

SMALLID 1. Jan 2007 14:26

Datenbank: XML (MyBase) • Zugriff über: TClientDataSet

TClientDataSet: AutoInc auch wirklich automatisch inc-en
 
Hallo, ich brauche in meinem Programm eine simple Datenbank, die nur lokal benutzt werden muss, aber Master/Detail Beziehungen unterstützen muss. Ich habe mich daher für das TClientDataSet entschieden und speichere damit zwei Tabellen ("UMTable" und "ArmTable") in zwei im Projektverzeichnis liegenden XML-Dateien ab.

UMTable hat folgende Fields:
Pos (Autoinc, wurde automatisch auf "fareadonly", "faunique" gesetzt)
MH_Name (string)
FS_Typ (string)
Name (string)

ArmTable hat folgende Fields:
Pos (siehe oben)
UMID (integer) (würde über MasterSource und Masterfields auf UMTable.Pos gemappt, geht wunderbar)
StartX (Float)
StartY (Float)
EndX (Float)
EndY (Float)

Meine Frage: Wenn ich nun das Programm starte und Werte bei UMTable oder ArmTable über ein DBGrid eingeben will, so sollte normalerweise automatisch ein neuer Wert bei Pos dastehen. (so bin ich es zumindest von Paradox Tabellen aus gewöhnt). Das Feld bleibt allerdings leer und erzeugt selbstverständlich beim Posten bzw. applyupdates eine Key Violation Exception.
Was mache ich denn da falsch, dass da kein autoinc wert kommt? Falls ich den selbst erzeugen muss, wie mache ihc dass mit dem tclientdataset am besten?

Vielen Dank für eure Hilfe!! :)

alzaimar 1. Jan 2007 14:31

Re: TClientDataSet: AutoInc auch wirklich automatisch inc-en
 
Du musst Dir dein 'AutoInc' selbst basteln. Dazu dient das Event 'OnNewRecord'. Hier weist Du dem 'AutoInc'-Feld (Der Datentyp muss -glaube ich- ein TIntegerFeld sein) einfach einen neuen Wert zu, z.B. so:

Delphi-Quellcode:
Procedure TDatamodule1.MyDataSetNewRecord (Sender : TDataset);
Begin
  inc (fUniqueID);
  Sender['IDFieldName'] := fUniqueID;
End;
Nun musst Du das private Feld 'fUniqueID' beim Einlesen der XML-Tabelle nur noch auf den höchsten Wert des Feldes 'IDFieldName' setzen und dann läuft das.

SMALLID 1. Jan 2007 16:00

Re: TClientDataSet: AutoInc auch wirklich automatisch inc-en
 
Vielen Dank! Es funktioniert! Schade, dass es von Delphi's Seite her keine elegantere Lösung für ein solches, häufig auftretendes Problem gibt.

alzaimar 1. Jan 2007 21:28

Re: TClientDataSet: AutoInc auch wirklich automatisch inc-en
 
SMALLID, findest Du 2 Zeilen *unelegant*?

Eigentlich unterstützen alle DB einen AutoInc, Du verzichtest hier ausnahmsweise darauf, weil Du die MyBase-Möglichkeiten eines TClientDatasets für eine Mini-DB misbrauchst. Also ich verwende auch (selten und im Zusammenhang mit local memory tables) einen so gestrickten AutoInc, aber ein 'häufig auftretendes Problem' ist das sicherlich nicht.

Schonmal an Access, ADS oder DBF gedacht?

SMALLID 2. Jan 2007 01:44

Re: TClientDataSet: AutoInc auch wirklich automatisch inc-en
 
Hi nochmal. Ok vllt. habe ich dann doch was falsch verstanden. 2 Zeilen wären ja schon super! :D Ich setze aber am Anfang für jede Tabelle erstmal den funiqueid wert, indem ich durchiteriere mit

Delphi-Quellcode:
  //autoinc werte für UMTable und ArmTable initialisieren
  fUMPosID := 1;
  UMTable.First;
  for i := 1 to UMTable.RecordCount do
  begin
    if UMTable.FieldByName('Pos').AsInteger > fUMPosID then
      fUMPosID := UMTable.FieldByName('Pos').AsInteger;
    UMTable.Next;
  end;
  fArmPosID := 1;
  ArmTable.First;
  for i := 1 to ArmTable.RecordCount do
  begin
    if ArmTable.FieldByName('Pos').AsInteger > fArmPosID then
      fArmPosID := UMTable.FieldByName('Pos').AsInteger;
    ArmTable.Next;
  end;
aber ggf. geht es noch anders?

Bisher habe ich immer nur Paradox Tabellen benutzt und in diesem Fall nutze ich MyBase, weil ich da weder BDE noch ADO Support auf dem Zielrechner brauche. Dachte eigentlich, dass jeder das TClientDataset für lokale DBs nimmt, oder ist da ODBC/ADO nach Access doch simpler?

alzaimar 2. Jan 2007 08:05

Re: TClientDataSet: AutoInc auch wirklich automatisch inc-en
 
Zitat:

Zitat von SMALLID
Hi nochmal. Ok vllt. habe ich dann doch was falsch verstanden. 2 Zeilen wären ja schon super! :D Ich setze aber am Anfang für jede Tabelle erstmal den funiqueid wert, indem ich durchiteriere mit

Na gut, die Initialisierung ist vielleicht noch dazuzurechnen.
Zitat:

Zitat von SMALLID
...
aber ggf. geht es noch anders?
Bisher habe ich immer nur Paradox Tabellen benutzt und in diesem Fall nutze ich MyBase, weil ich da weder BDE noch ADO Support auf dem Zielrechner brauche. Dachte eigentlich, dass jeder das TClientDataset für lokale DBs nimmt, oder ist da ODBC/ADO nach Access doch simpler?

Erstens geht es einfacher und zweitens ist ADO sowieso auf jedem Windows-PC installiert. Ich würde persönlich (aber nur bei Einzelplatzanwendungen) Access per ADO verwenden. Für Standard-Anwendungen reicht das Dicke und macht die Entwicklung zum Kinderspiel.

Delphi-Quellcode:
Function GetMaxID (aTable : TDataset; IDField : String) : Integer;
Var
  fField : TField;
  B : TBookmark;
Begin
  Result := -maxInt;
  fField := aTable.FieldByName(IDField);
  aTable.DisableControls;
  aTable.GetBookmark (B);
  Try
    aTable.First;
    While not aTable.Eof Do Begin
      If Result < fField.AsInteger Then
        Result := fField.AsInteger;
      aTable.Next;
    End;
  Finally
    aTable.GotoBookmark (B);
    aTable.FreeBookmark (B);
    aTable.EnableControls;
  End;
End;
Im DataModuleCreate wird für alle Tabellen dann GetMaxID aufgerufen und der Wert in den privaten Feldern gespeichert. Noch einfacher ist es, die MaxID in der Tag-Eigenschaft der Tabelle zu speichern:
Delphi-Quellcode:
Procedure TMyDataModule.DataModuleCreate (Sender : TObject);
Begin
  Table1.Tag := GetMaxId (Table1);
  Table2.Tag := GetMaxId (Table2);
  Table3.Tag := GetMaxId (Table3);
  Table4.Tag := GetMaxId (Table4);
  Table1.OnNewRecord := TMyDataModuleNewRecrd;
  Table2.OnNewRecord := TMyDataModuleNewRecrd;
  Table3.OnNewRecord := TMyDataModuleNewRecrd;
  Table4.OnNewRecord := TMyDataModuleNewRecrd;
End;

Procedure TMyDataModule.DataModuleCreate (Sender : TDataset);
Begin
  Sender.Tag := Sender.Tag + 1;
  Sender[IDField] := Sender.Tag;
End;
Ich würd trotzdem Access nehmen. Ist doch schön stabil (bei einer Einzelplatzanwendung).

SMALLID 2. Jan 2007 10:48

Re: TClientDataSet: AutoInc auch wirklich automatisch inc-en
 
Das ist ja cool mit dem ADO/Access! Ich hatte immer gedacht, dass man da auch bei der Installation noch Komponenten in der Manier von BDE oder .NET Framework hinzufügen muss oder zumindest Office installiert sein muss. Peinlich Peinlich *rotwerd*, naja ich hatte bisher wie gesagt nur Paradox benutzt (weil ich auch bisher nur Delphi 4 Pro gekauft hatte und leider keine Mittel für ein neues Delphi da waren - jetzt hab ich aber 7 Pro hier und BDS2006 an der Uni :D) aber wenn das ADO so auch funktioniert werde ich ab jetzt lieber Access für sowas verwenden. Dann klappt's auch wieder mit'm AutoInc ;) :D Danke nochmal!

Christian Seehase 2. Jan 2007 11:45

Re: TClientDataSet: AutoInc auch wirklich automatisch inc-en
 
Moin Zusammen,

Zitat:

Zitat von alzaimar
Na gut, die Initialisierung ist vielleicht noch dazuzurechnen.

wobei man ja die zuletzt benutzte ID auch einfach in einer Konfigurationsdatei speichern könnte.

marabu 2. Jan 2007 21:04

Re: TClientDataSet: AutoInc auch wirklich automatisch inc-en
 
Hallo Chris,

wenn man bei der Erzeugung von Identitäten nicht auf die Unterstützung des Datenbanksystems zählen kann, dann sind schon deutlich mehr als zehn Zeilen Code nötig um einen Mehrbenutzerbetrieb zu ermöglichen. So darf z.B. das Programm keinen weiteren Programm-Instanzen den Zugriff auf die Konfigurationsdatei gestatten, solange das Konzept lediglich das Auslesen des Startzählers beim Programmstart vorsieht. Ist schon besser, wenn man mit AutoInc bzw Identity arbeitet.

Freundliche Grüße


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