Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Transactionen (https://www.delphipraxis.net/139117-transactionen.html)

clock50 24. Aug 2009 00:55

Datenbank: Firebird • Version: 2.0 • Zugriff über: IBX

Transactionen
 
Hallo Leute,

ich habe mich mal über IBX und Firebird belesen. Zugreifen ändern einfügen geht alles nur mit zwei oder meheren Progammen auf eine DB das will immer noch nicht so recht.
Ich habe alle Ratschläge versucht umzusetzen. Aber ich komme noch nicht so recht klar.
Also habe ich für jeden zugriff ob lesen, einfügen oder ändern jedes mal StartTransaction nach lesen ein Rollback nach ändern oder einfügen ein Commit.
jetzt bekomme ich immer wieder die Meldung Transaction ist aktiv oder Transaction ist nicht activ obwohl direkt vor dem IBQuery ... ein StartTransaction steht.

Ich benutze keine Datasource, ich lade alles in listen und lasse es über Listview anzeigen.

Delphi-Quellcode:
procedure TDM.sSql(Sql : String);
begin
  IBTransaction1.StartTransaction;
  IBSQL1.SQL.Clear;
  IBSQL1.SQL.Text := Sql;
  IBSQL1.ExecQuery;
  IBTransaction1.Commit;
end;

procedure TDM.F2Anzeige(ID : Integer);
begin
 if not Assigned(Form2) then exit;
 if Form2.WindowState = wsMinimized Then exit;

 IBTransaction1.StartTransaction;
 IBQuery1.Open;
 IBQuery1.Locate('ID', kunden[id].id, [loCaseInsensitive]);
 k_ID := DM.IBQuery1ID.AsInteger;
 Form2.JvComboBox1.Text := DM.IBQuery1ANREDE.AsString;
 Form2.JvEdit1.Text := DM.IBQuery1VORNAME.AsString;
 Form2.JvEdit2.Text := DM.IBQuery1NAME.AsString;
 Form2.JvComboBox2.Text := DM.IBQuery1LAND.AsString;
 Form2.JvEdit3.Text := DM.IBQuery1PLZ.AsString;
 Form2.JvEdit4.Text := DM.IBQuery1ORT.AsString;
 Form2.JvEdit5.Text := DM.IBQuery1STRASSE.AsString;
 Form2.JvEdit6.Text := DM.IBQuery1TEL.AsString;
 Form2.JvEdit7.Text := DM.IBQuery1FAX.AsString;
 Form2.JvEdit8.Text := DM.IBQuery1MAIL.AsString;
 Form2.JvEdit9.Text := DM.IBQuery1KNR.AsString;
 IBQuery1.Close;
 IBTransaction1.Rollback;
end;

function TDM.Kundeneu : integer;
begin
 IBTransaction1.StartTransaction;
 Abfrage.Close;
 Abfrage.SQL.Clear;
 Abfrage.SQL.Add('SELECT * FROM KUNDEN ORDER BY CAST(KNR AS INTEGER) ASC');
 Abfrage.Open;
 Abfrage.Last;
 Result := Abfrage.FieldByName('KNR').AsInteger + 1;
 IBTransaction1.Rollback;
end;

procedure TDM.DKunden(SQL : String);
var a : integer;
    itm : TListItem;
begin
 IBTransaction1.StartTransaction;
 if SQL <> '' Then
  begin
  IBQuery1.Close;
  IBQuery1.SQL.Clear;
  IBQuery1.SQL.Add(sql);
  end;
 IBQuery1.Open;
 SetLength(Kunden, 1);
 IBQuery1.First;
 While not IBQuery1.Eof do
  begin
  setlength(kunden, length(kunden)+1);
  a := length(kunden)-1;
  kunden[a].id := IBQuery1ID.AsInteger;
  kunden[a].knr := IBQuery1KNR.AsInteger;
  kunden[a].name := IBQuery1NAME.AsString;
  kunden[a].vorname := IBQuery1VORNAME.AsString;
  IBQuery1.Next;
  end;
  IBQuery1.Close;
  IBTransaction1.Rollback;
end;

procedure TDM.AKunden(ListView : TJvListView);
var a : integer;
    itm: TListItem;
begin
 ListView.Items.Clear;
 for a := 1 to Length(kunden)-1 do
  begin
  itm := ListView.Items.Add;
  itm.Caption := IntToStr(kunden[a].id);
  itm.SubItems.Add(kunden[a].vorname);
  itm.SubItems.Add(kunden[a].name);
  end;
 ListView.Items[ListView.Items.Count-1].MakeVisible(True);
 if a < 0 then ListView.ItemIndex := ListView.Items.Count-1 else ListView.ItemIndex := a;
 F2Anzeige(a);
 unit3.KuNr := IntToStr(kunden[a].knr);
 unit4.KuNr := IntToStr(kunden[a].knr);
end;

sx2008 24. Aug 2009 05:03

Re: Transactionen
 
Zitat:

Zitat von clock50
Ich benutze keine Datasource, ich lade alles in listen und lasse es über Listview anzeigen.

Warum eigentlich nicht? Ist das zu einfach?
Mir fällt auserdem auf, dass du dein Datenmodul und das Formular auf sehr ungünstige Weise
vermischt.
In procedure TDM.F2Anzeige(ID : Integer) kennt das Datenmodul das Formular (das ist schlecht)
und das Fomular kennt das Datenmodul (das ist in Ordnung).
Ehrlich gesagt ist die Procedure eine einzige Katastrophe. Nicht mal das Ergebnis von Locate wird überprüft.
Wenn du z.B. TForm2.JvEdit5 einen sinnvollen Namen geben möchtest, musst du gleich an zwei Stellen ändern.

Ich schlage vor, TDatasource und TEdit Objekte zu benützen.
Dadurch wird die Kopplung zwischen Formular und Datenmodul automatisch verringert und ausserdem ist Funktionalität für die du stundenlang programmieren müsstest schon vorhanden.

Um eine neue Kundennummer zu ermitteln, brauchst du nicht alle Daten abrufen und diese dann auch noch sortieren.
Delphi-Quellcode:
function TDM.Kundeneu : integer;
begin
  Abfrage.SQL.Add('SELECT MAX(KNR)+1 FROM KUNDEN');
  Abfrage.Open;
  result := Abfrage.Fields[0].AsInteger;
  Abfrage.Close;
end;
Ansonsten würde ich keinerlei Transactions benützen, sondern alles so einfach wie möglich halten.
Transactions werden erst dann wichtig, wenn z.B. mehrere Arbeitsstationen auf die gleichen Daten zugreifen oder Änderungen an mehreren Tabellen ganz oder gar nicht vorgenommen werden müssen.

mkinzler 24. Aug 2009 05:37

Re: Transactionen
 
Eine neue Kundennummer sollte aber über einen Generator plus GenID() erfolgen

clock50 24. Aug 2009 05:46

Re: Transactionen
 
Ich möchte ja grundsätzlich verstehen wie das mit mehrern anwendungen auf eine datenbank ist. die Datasource habe ich weggelassen da die Transaction sonst offen bleiben muß und eine Andere Anwendung nicht die daten bearbeiten kann.

hoika 24. Aug 2009 08:43

Re: Transactionen
 
Hallo,

jeder hat mal angefangen,
also nicht immer gleich losschreien ;)


Zitat:

jetzt bekomme ich immer wieder die Meldung Transaction ist aktiv
Die Meldung ist doch aussagekräftig, oder ?
Irgendwo wird die Transaktion doch nicht geschlossen

Dein Code

Delphi-Quellcode:
procedure TDM.sSql(Sql : String);
begin
  IBTransaction1.StartTransaction;
  IBSQL1.SQL.Clear;
  IBSQL1.SQL.Text := Sql;
  IBSQL1.ExecQuery;
  IBTransaction1.Commit;
end;

Mein Code:

Delphi-Quellcode:
procedure TDM.sSql(Sql : String);
begin
  IBTransaction1.StartTransaction;
  try
    try
      IBSQL1.SQL.Clear;
      IBSQL1.SQL.Text := Sql;
      IBSQL1.ExecQuery;
    except
      IBTransaction1.RollBack;
    end;
  finally
    if IBTransaction1.InTransaction then
    begin
      IBTransaction1.Commit;
    end;
  end;
end;
Das begin/end beim Commit erlaubt es übrigens,
einen Breakpoint zu setzen (bei der Fehlersuche ganz hilfreich)

Nutze als try/except, try/finally wie ich.


Eine letzte Sache, die DataBases/Transaktionen sollten nicht im Object-Inspector
geöffnet/aktiv gesetzt werden.



Heiko

clock50 24. Aug 2009 20:38

Re: Transactionen
 
Hallo Heiko,

das hat mich ein ganze Stück weiter gebracht, Danke.

Aber nur mal so am Rande : Ist es überhaupt möglich wenn man TDatasource verwendet "gleichteitige" zugriffe auf eine DB mit IBX oder ZEOS. Es ist ja immer geöffnet wenn man DBGrid auch noch hat und die Daten permanet angezeigt werden?

mkinzler 24. Aug 2009 20:40

Re: Transactionen
 
Du mustt die datenmengen halt entsprechend auffrischen (.Refresh). Z.B. durch Events

hoika 25. Aug 2009 07:54

Re: Transactionen
 
Hallo,

oder ein TClientDataSet für die DBGrid-Anzeige verwenden.
Ich persönlich benutze DBGrid gar nicht,
sondern ein normales StringGrid.


Heiko

clock50 25. Aug 2009 11:46

Re: Transactionen
 
Ich verwende sehr gerne ListView weil es den Inhalt nur verdeckt wenn er für dei zelle zugroß ist und wenn man mit der maus darüber geht zeigt er den rest in Hit ohne eine zeile code.


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