Hallo,
ich habe vor einen Datenbankabfrage durchzuführen, welche mehrere Minuten dauern kann. Da dieses in einem Windowsservice laufen soll, muss ich unter bestimmten Bedingungen (stoppen vom Service etc.) das Programm schnellst möglich stoppen können. Wie kann ich im folgendem Coldeauszug den Abbruch erkennen und die SQL Abfrage abzubrechen.?
using (OracleConnection connection = new OracleConnection())
{
connection.ConnectionString = connectionString;
connection.Open();
OracleCommand command = connection.CreateCommand();
OracleDataReader reader;
string sql;
sql = "SELECT * FROM TESTVIEW ";
command.CommandText = sql;
reader = command.ExecuteReader();
...
Das Abbrechen wird in Form von einer Variable vorliegen ... sprich wenn zB. die Variable sys_cancel auf true gesetzt wird soll die SQL Abfrage stoppen.
Gibt es da eine Lösung?
Danke für eure Hilfe
mfG Hans
Ich würd dir vorschlagen das ganze mit einer Transaction zu machen
using (OracleConnection myConnection = new OracleConnection())
{
myConnection = AGB70.PABS.Common.Var.gblDBInfo.GetDbConnection();
myConnection.Open();
//Definiert den Start einer Übertragung
myTransaction = myConnection.BeginTransaction(); //vielleicht noch isolationslevel hinzufügen
//Erstellt ein Commandobjekt, welches die SQL-Statements ausführt
myCommand = AGB70.PABS.Common.Var.gblDBInfo.GetDbCommand();
mytCommand.Connection = myConnection;
mytCommand.Transaction = myTransaction;
}
so kannst du schlussendlich mit rollback alles rückgängig machen
if (sys_cancel)
{
myTranscation.Rollback();
}
ps. am schluss nicht den commit vergessen
Hallo!
Man könnte auch alles in einen separaten Thread packen, und diesen dann bei bedarf beenden. Dadurch wird auch die Abfrage beendet.
Nobody is perfect. I'm sad, i'm not nobody 🙁
Hallo,
danke schon mal für die ersten vorschläge.
@chanderegg
Das mit der Transaktion habe ich glaube nicht 100% verstanden. Da ich nur Abfragen (SELECT) verarbeite, werde ich kein Rollback benötigen.
Mein Problem ist viel mehr das das die Abfrage alleine schon mehrere Minuten benötigt.
@tom-essen
Die Idee mit dem separaten Theader hatte ich auch schon, aber die Idee wollte ich nicht weiter verfolgen, da das ja bedeuten würde, das ich die Oracle Verbindung "abschieße" und ich so eventuell Fehler und Deadlocks erzeuge könnte.
Kann man so einen hartes abschießen nicht irgendwie verhindern?
Bei meinem Datenbank Tool (Toad) kann man die SELECT Anweisungen auch schön sauber abbrechen.
mfG Hans
Hallo,
Du könntest Deine sid (session instance identifier) und die serial# vor der lang laufenden Anfrage auslesen (v$session?) und mit ALTER SYSTEM KILL SESSION in einem anderen Thread beenden,.
Hallo witte,
wenn ich mir das richtig durchgelesen habe, müsste ich um sicher zu stellen, das die Session gekillt wird wirklich hart killen mit diesem -9. ... hmm so toll finde ich das aber auch nicht, meinem Programm einfach die Oracle Session weg zu nehmen.
Es muss doch möglich sein, die Transaktion sauber zu beenden (auf einem dafür vorgesehenen Weg) ohne ein kill oder ähnliches.
So nach dem Motto, cancel Transaktion xy ... und Oracle bricht dann kontrolliert die Anfrage ab.
Ich bin ganz ehrlich von diesem "Ach beenden / killen wir es einfach hart ... wird schon nichts passieren" halte ich nicht alt so viel ... Am Ende gibt das nur Probleme.
Ich bin ganz ehrlich von diesem "Ach beenden / killen wir es einfach hart ... wird schon nichts passieren" halte ich nicht alt so viel ... Am Ende gibt das nur Probleme. Das ist quatsch. Ein Serversystem taugt nichts wenn es durch solche Abbrüche in die knie zwingen läßt. Wäre ja ne prima DOS-Attacke.
Aber Du sollst ja nicht den OS-Prozeß killen sondern die Oracle-Session. Ich glaube nicht dass das auf Transaktionsebene geht. Dein TOAD wird es wahrscheinlich auch so handhaben: die SID aus der ersten Transaktion vorher auslesen und in einer zweiten Verbindung abbrechen. Du kannst ja mal mit einem Profiler/Wireshark den Datentransfer mitschneiden und schauen was bei TOAD passiert.
huhu,
eine Transaktion abzubrechen schadet keinem DB-System. Genau dafür sind Transaktionen da. Auch das beenden einer Verbindung sorgt in dem Fall für einen Rollback der Transaktion. Sogar bei einem Stromausfall wird im Normalfall beim wiederanlaufen der DBs geguckt, ob man noch ein paar transaktionen, welche nicht fertig waren, wieder rückgängig machen muss.
Für dein Problem gibts aber IDbCommand.Cancel(). Dann würde ich aber auch zusätzlich die BeginXXX-Methoden verwenden um das ganze asynchron zu halten.
😃
xynratron
Herr, schmeiss Hirn vom Himmel - Autsch!
Die Erfahrung zeigt immer wieder, dass viele Probleme sich in Luft auslösen, wenn man sich den nötigen Abstand bzw. Schlaf gönnt.
Hallo,
das mit der IDbCommad.Cancel() klingt doch gut, kann mir dazu eventuell mal ein beispiel geben ... denn ich hänge bei dieser Idee an dem Punkt, wo ich der Meinung bin, das mein Programm beim
reader = command.ExecuteReader();
solange wartet, bis dieser Befehl durch gelaufen ist. und somit kann ich ja das Cancel nicht durchführen oder?
Weshalb dir Xynratron auch gleich geraten hat die Asynchronen Beginxxx Funktionen zu nutzen.
Achso ... den Befehl gibt es wirklich ... ich dachte das mit dem xxx war mehr ein Beispiel ... ist das sowas wie der Backgroundworker?