![]() |
Datenbank: Access MDB • Zugriff über: ADO
Schneller SQL Zugriff macht Probleme
Hallo DP-Gemeinde,
ich hätte mal wieder ein Problem: Ich möchte eine Liste der aktuellen Fehler mehrerer Clients, die auf einem Server gespeichert sind (Für jeden Client ein eigenes File) in einem Form anzeigen, wobei noch zusätzliche Information aus einer lokalen Datenbank (Access .mdb) ausgelesen und dazugenommen werden soll. Zu diesem Zweck werden die einzelnen Files in eine eigene lokale Tabelle geschrieben und dann über ein JOIN mit der zusätzlichen Information verknüpft und per DBGrid ausgegeben. Das funktioniert auch soweit, allerdings momentan eher als Faulthistory, da alle Fehler gespeichert werden und bleiben. Bevor ich nun die neuen Datensätze schreibe, muss ich also die alten löschen. Das erledige ich über eine zweite ADOQuery uznd nun kommt das hüpfende Komma: Sobald ich lösche funktioniert das Ganze eine Weile wie es soll, verabschiedet sich jedoch relativ schnell mit: EOleException: Aktualisierung nicht möglich; momentan gesperrt. :pale: Irgendwie kommen sich dabei anscheinend die Abfragen ins Gehege. Ich sollte noch erwähnen, dass für alle Clients das selbe Fenster geöffnet wir, und über die ID die Fehlermeldungen ausgewählt werden. Genug Gefasel hier der Quelltext
Delphi-Quellcode:
Hoffe es kann jemand helfen :coder2:
(***************************
** Function: ShowAlarms ** **************************** ** Show the active alarms ** ** with a database grid ** ***************************) function TForm_ActiveFault.ShowAlarms():Integer; var i : Integer; ID_Str : String; Status : Integer; begin Status := 0; try (* TODO: Testversion: The deleteprogress produces an error *) DataModule1.ADOQueryFaultAct.Close; (* TODO : Testversion: deletes the active faults of the current client from the ADO table *) Datamodule1.ADOQueryFaultDel.Close; Datamodule1.ADOQueryFaultDel.SQL.Clear; Datamodule1.ADOQueryFaultDel.SQL.Text := 'DELETE * FROM Fault_Active WHERE Client_ID = ' + IntToStr (Curr_Client_ID); Datamodule1.ADOQueryFaultDel.ExecSQL; Datamodule1.ADOQueryFaultDel.Close; Datamodule1.ADOTableFaultAct.Active := True; Datamodule1.ADOTableFaultAct.First; ID_Str := IntToStr(Curr_Client_ID); (* Read the active faults from the server into the stringgrid *) Read_CSV_File (ACTIVEALARMS_Path + 'active' + ID_Str, #9, StringGrid_Hide); (* Write the content of the stringgrid into the ADO Table *) for i := 1 to Pred(StringGrid_Hide.RowCount) do begin StringGrid_Hide.Cells[1,i-1] := DateTimeToStr(Now); if StringGrid_Hide.Cells[3,i-1] = '' then StringGrid_Hide.Cells[3,i-1] := '0'; Datamodule1.ADOTableFaultAct.Append; Datamodule1.ADOTableFaultAct.FieldByName ('Client_ID') .AsString := ID_Str; Datamodule1.ADOTableFaultAct.FieldByName ('Name') .AsString := StringGrid_Hide.Cells[0,i-1]; // Faultname Datamodule1.ADOTableFaultAct.FieldByName ('StartTime') .AsString := StringGrid_Hide.Cells[1,i-1]; // StartTime Datamodule1.ADOTableFaultAct.FieldByName ('Code') .AsString := StringGrid_Hide.Cells[2,i-1]; // Code Datamodule1.ADOTableFaultAct.FieldByName ('Subcode') .AsString := StringGrid_Hide.Cells[3,i-1]; // Subcode Datamodule1.ADOTableFaultAct.FieldByName ('Priority') .AsString := StringGrid_Hide.Cells[4,i-1]; // Priority Datamodule1.ADOTableFaultAct.Next; end; DataModule1.ADOTableFaultAct.Close; // DataModule1.ADOTableFaultAct.EnableControls; DataModule1.ADOQueryFaultAct.SQL.Clear; (* Read the active alarms of the current client from the Fault_Active table and *) (* connect them with the information from the 'Fault_Definition' table *) DataModule1.ADOQueryFaultAct.SQL.Text := 'SELECT Fault_Active.Code As Code, ' + ' Fault_Active.SubCode As Subcode, ' + ' Fault_Definition.Priority As Priority, ' + ' Fault_Active.StartTime As StartTime, ' + ' Fault_Definition.DisplayName As FaultText, ' + ' Fault_Definition.description As Description, ' + ' Fault_Definition.manualRef As Reference ' + ' FROM Fault_Definition, Fault_Active ' + ' WHERE Fault_Definition.Name = Fault_Active.Name ' + ' AND Fault_Definition.Client_ID = Fault_Active.Client_ID ' + ' AND Fault_Definition.Client_ID = ' + IntToStr (Curr_Client_ID) + ' ORDER BY Fault_Active.StartTime ASC'; DataModule1.ADOQueryFaultAct.ExecSQL; DataModule1.ADOQueryFaultAct.Open; (* Pass the FieldNames of the queryresult to the DBGrid *) DBGrid_Active.Columns[0].FieldName := 'Code'; DBGrid_Active.Columns[1].FieldName := 'Subcode'; DBGrid_Active.Columns[2].FieldName := 'Priority'; DBGrid_Active.Columns[3].FieldName := 'StartTime'; DBGrid_Active.Columns[4].FieldName := 'FaultText'; DBGrid_Active.Columns[5].FieldName := 'Description'; DBGrid_Active.Columns[6].FieldName := 'Reference'; for i := 1 to Pred(StringGrid_Hide.RowCount) do begin if StrToInt(StringGrid_Hide.Cells[4,i-1]) > Status then Status := StrToInt(StringGrid_Hide.Cells[4,i-1]); end; except begin Release_ActiveFault := False; Messagebox(Handle, PChar('Disturbed database connection'), PChar('Database fault'), MB_OK or MB_ICONWARNING); end; end; Result := Status; end; PS: Ich weiß, dass die Idee in die Datenbank zu schreiben und kurz darauf wieder zu löschen nicht die tollste ist, mir ist aber keine bessere Möglichkeit eingefallen, die in der zweiten Datenbank gespeicherten Infos mit den Files der einzelnes Clients zu verknüpfen ... |
Re: Schneller SQL Zugriff macht Probleme
Das Problem hat sich erledigt.
1. Wurde der Timer der die Funktion gestartet hat nicht beendet, wodurch dann bei Schließen und Neuöffnen des Fensters für einen anderen Client die Querys doppelt verwendet wurden, was zum Crash führte 2. Wurden die Querys anscheinend zu schnell nacheinander ausgeführt, so dass der Tabellenzugriff noch nicht wirklich beendet war. Ein Delay zwischen den Querys schfft Abhilfe. Das erste DataModule1.ADOQueryFaultAct.Close; musste letztendlich auch weichen, da sonst immer eine kurze Zeitspanne nichts im DBGrid angezeigt wurde, bis die neuen Daten da waren. |
Re: Schneller SQL Zugriff macht Probleme
Zitat:
Wichtig: deine Anwendung braucht genau eine TADOConnection Komponente. Alle TADOQuery, TADOTable, TADODataset und TADOCommand müssen auf diese eine Connection verweisen. Sollte es nämlich mehrere Datenbankverbindungen geben, dann sieht die Verbindung B die Daten von Verbindung A erst nach ~ 2.5 Sekunden Verzögerung. |
Re: Schneller SQL Zugriff macht Probleme
Hi, hab das grade mal probiert, über eine TADO Connection zu gehen (Zuvor hab ich für jede table einen Connection String bei Laufzeit zugewiesen)
Mit nur einer TADO Connection bekomm ich jetzt aber auch wieder Zugriffsverletzungen in der Art wie zuvor. |
Re: Schneller SQL Zugriff macht Probleme
Zitat:
Zum Beispiel sind die Zeilen nach (* Pass the FieldNames of the queryresult to the DBGrid *) falsch, da ein DBGrid seine Spalten eigenständig an die Felder bindet. Wenn das DBGrid weniger als 7 Spalten hat, gibt es eine Zugriffsverletzung. Um die Felder in eine bestimmte Reihenfolge zu bringen, gibt es schönere Möglichkeiten. Du hast kein Sicherheitsnetz aufgespannt. Zum Beispiel DataModule1.ADOQueryFaultAct.Close - bist du 100% sicher, dass die Variable DataModule1 überhaupt auf ein Datenmodul zeigt ?
Delphi-Quellcode:
Deine Exceptionbehandlung ist auch falsch, da du die eigentliche Fehlermeldung komplett unter den Tisch fallen lässt.
Assert(Assigned(DataModule1)); // sicherstellen, dass Datenmodul vorhanden
try DataModule1.ADOQueryFaultAct.Close; ... Du solltest auf jeden Fall nur mit einer ADOConnection arbeiten und deine Zugrfiffsverletzungen mit dem Debugger ausmerzen. |
Re: Schneller SQL Zugriff macht Probleme
mal eine andere frage, weshalb verwendest du denn datensensitive komponenten?
das könntest du doch auch mit 'n normalen stringgrid abbilden und das füllen selbst übernehmen :-) damit erstparst du dir die ganzen komplikationen und das progy wird viel runder :-) |
Re: Schneller SQL Zugriff macht Probleme
Erst mal Danke für die Antworten
@ shmia: Okay, die unsauberen Stellen werd ich versuchen auszubessern. Zu den schöneren Methoden die Reihenfolge festzulegen: Könntest du da mal welche nennen? Wenn ich meinem Grid nämlich sieben Spalten zuweise, und ich denke das muss ich tun, um den Spalten ihre Größe zuzuweisen, muss ich dann auch die Spaltennamen zuweisen, da sonst nichts im Grid erscheint. Wenn ich damit auf dem Holzweg bin, bitte ich um Berichtigung. @grenzgaenger: Das Problem ist, dass ich eine Tabelle mit Fehlerbeschreibungen vorliegen habe, in denen eben alle für ein Gerät möglichen Fehler gelistet sind. Hier muss ich nun mittels Select zumindest mal die benötigten raussuchen. Hab ich schon die Select Anweisung kann ich deren Ergebnis auch gleich in ein DBGrid schreiben. So war jedenfalls mein Gedankengang. Wenn das effizienter bzw. einfacher geht lass ich mich gerne belehren. :coder: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:19 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz