Autor |
Beitrag |
DeadlyAppearance
      
Beiträge: 113
Win 7
Delphi 2010 Arch., C# VS 2008
|
Verfasst: Do 20.08.09 16:54
Abend zusammen.
Ich bin neu bei C# und habe folgendes Problem.
Mein Mainthread erstellt eine Datenbankverbindung und soll so lange immer wieder ein Select auf eine Tabelle machen, bis dort eine Abbruchdatensatz vorhanden ist.
Jetzt habe ich jedoch das Problem, dass sich nach dem connection.Open(); nur einmal command.ExecuteReader(); aufrufen kann, ohne erneut die Verbindung zu Beenden und erneut eine aufzubauen. Macht in meinen Augen natürlich keinen Sin, in einer Whileschleife alle Sekunde ne neue Verbindung aufzubauen, nur um den Inhalt einer Tabelle zu prüfen.
Wie also kann ich mein Command immer wieder ausführen und mit dem neuen Inhalt arbeiten, ohne ständing eine neue Verbindung aufbauen zu müssen?
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
| while (!stoped) { connection.Open(); Reader = command.ExecuteReader();
while (Reader.Read()) { if (Reader.GetUInt32(1) == 1) { Console.WriteLine(Reader.GetValue(0).ToString()); } if (Reader.GetUInt32(1) == 255) { stoped = true; } }
connection.Close();
Thread.Sleep(1000); }
|
_________________ Als du auf die Welt kamst, weintest du, und um dich herum freuten sich alle. Lebe so, daß, wenn du die Welt verläßt, alle weinen und du allein lächelst.
|
|
JüTho
      
Beiträge: 2021
Erhaltene Danke: 6
Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
|
Verfasst: Do 20.08.09 18:02
Hallo,
es hängt vom DBMS (einschl. Version) und dem DbProvider ab, ob und wie es überhaupt möglich ist. Unter OleDbCommand.ExecuteReader heißt es beispielsweise als Hinweis in der SDK-Doku/MSDN:
Zitat: | Während der OleDbDataReader verwendet wird, ist die zugeordnete OleDbConnection durch den Informationsfluss für den OleDbDataReader belegt. In diesem Zustand können an der OleDbConnection keine anderen Operationen ausgeführt werden, außer diese zu schließen. Dies gilt solange, bis die Close-Methode von OleDbDataReader aufgerufen wird. |
Aber das, was du vorhast, belastet sowieso die DB-Anbindung enorm; du solltest dir ein anderes Verfahren ausdenken.
Vor allem musst du beachten, dass unter NET eine DbConnection immer nur kurzfristig aktiv ist und so schnell wie möglich wieder geschlossen wird. Empfohlenes Vorgehen ist deshalb der using-Block um die Connection:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| using( DbConnection conn = new DbConnection(connString) ) { using( DbCommand cmd = new DbCommand(cmdString, conn) ) { conn.Open(); DbDataReader reader = cmd.ExecuteReader();
while (reader.Read()) { } reader.Close(); } } |
Bei diesem Verfahren wird die DbConnection immer korrekt aufgelöst.
Gruß Jürgen
|
|
DeadlyAppearance 
      
Beiträge: 113
Win 7
Delphi 2010 Arch., C# VS 2008
|
Verfasst: Do 20.08.09 18:29
Ahh, das reader.Close(); hat bereits das Problem gelöst.
Was genau mit der using der Unterschied ist, muss ich mal lesen.
Jedoch wird nur beim Programmbegin eine Connection aufgebaut und die bleibt auch bestehn bis zum Ende.
Verstehe also nicht ganz, was Zitat: | belastet sowieso die DB-Anbindung enorm |
zu bedeuten hat.
_________________ Als du auf die Welt kamst, weintest du, und um dich herum freuten sich alle. Lebe so, daß, wenn du die Welt verläßt, alle weinen und du allein lächelst.
|
|
JüTho
      
Beiträge: 2021
Erhaltene Danke: 6
Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
|
Verfasst: Do 20.08.09 19:08
Zur Lebensdauer von Connections siehe [Artikel] Ressourcen schonen - Datenbanken richtig öffnen und schließen
Zum using-Block siehe u.a. Die »using«-Anweisung zur Zerstörung von Objekten. Der letzte Absatz dort lautet:
Zitat: | Die Klasse, die im Ausdruck instanziiert wird, muss eine Bedingung erfüllen: Sie muss die Schnittstelle IDisposable implementieren. |
Dies kann sogar umgekehrt formuliert werden: Jede Klasse, die IDisposable enthält, sollte auf diese Weise mit using-Block benutzt werden.
Jürgen
|
|
DeadlyAppearance 
      
Beiträge: 113
Win 7
Delphi 2010 Arch., C# VS 2008
|
Verfasst: Fr 21.08.09 00:05
Vielen Dank für die Tolle Hilfe und die beiden informativen Links.
_________________ Als du auf die Welt kamst, weintest du, und um dich herum freuten sich alle. Lebe so, daß, wenn du die Welt verläßt, alle weinen und du allein lächelst.
|
|
DeadlyAppearance 
      
Beiträge: 113
Win 7
Delphi 2010 Arch., C# VS 2008
|
Verfasst: Fr 21.08.09 14:50
Wow, das rennt ja nun richtig.
Aus welchem Grund ist das denn nun so rasend schnell zu meiner vorherigen Ausführung?
Kann man das jetzt so lassen?
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44:
| static void Main(string[] args) { Console.WriteLine("{0:T} | Server gestartet", DateTime.Now); bool stoped = false;
string myConnectionString = "SERVER=localhost;" + "DATABASE=xxx;" + "UID=xxx;" + "PASSWORD=xxx;";
while (!stoped) { using (MySqlConnection connection = new MySqlConnection(myConnectionString)) { using (MySqlCommand command = new MySqlCommand("SELECT * FROM xxx", connection)) { connection.Open();
MySqlDataReader Reader = command.ExecuteReader(); while (Reader.Read()) { if (Reader.GetUInt32(1) == 1) { Thread TNewAccount = new Thread(new ParameterizedThreadStart(CreateAccount.MyProcedure)); TNewAccount.Start(Reader.GetUInt32(0)); } if (Reader.GetUInt32(1) == 255) { stoped = true; } } Reader.Close(); } } }
Console.WriteLine("{0:T} | Server gestoppt", DateTime.Now); Console.ReadLine(); } } |
_________________ Als du auf die Welt kamst, weintest du, und um dich herum freuten sich alle. Lebe so, daß, wenn du die Welt verläßt, alle weinen und du allein lächelst.
|
|
|