Laden...

DataReader.Close

Erstellt von SuperThoms vor 18 Jahren Letzter Beitrag vor 18 Jahren 2.328 Views
S
SuperThoms Themenstarter:in
1 Beiträge seit 2005
vor 18 Jahren
DataReader.Close

Hallo,

Ich benutze den OleDB Adapter um einen SQL Server zuzugreifen.
Jetzt habe ich eine Tabelle mit ca 1,3 Millionen Einträgen, die ich mit dem DataReader in einer Schleife runterziehe:

			while(r.Read())  
			{  
				i++;  

.....

				if (i>500000)  
					break;  
			}  

Allerdings will ich z.B. nur die ersten 500.000 Datensätze haben.

Wenn man nun ein Close des DataReader sausführt, ohne dass man alle Datensätze verwendet hat, werden diese aber anscheinend trotzdem noch runtergeladen, wie man am Netzwerktraffic sehen kann. Außerdem dauert das Close() ca. 40 Sekunden.
Wenn man alle Daten runterlädt hat man diese Probleme natürlich nicht.

Gibt es eine saubere Lösung (also keine neue Datenbankverbindung, obwohl das wunderbar funktioniert 🙂 ) um den DataReader schnell zu schließen?

Gruß

Thomas

S
223 Beiträge seit 2005
vor 18 Jahren

Kannst du nicht vorher ein Select machen für deinen Reader, der dann halt nur die Daten holt, die du möchtest? Ich verwende nicht den OleDB Adapter, aber in MySQL gibt es das hier:


string sql = "SELECT feldname FROM tabelle where ID < 500000;";
MySqlCommand cmd = new MySqlCommand(sql, myCon);
reader = cmd.ExecuteReader();    							
while(reader.Read()) 
{							string was_auch_immer = (string)reader["feldname"];
}
reader.Close();

Sicherlich wird es das auch äquivalent bei OleDB geben?! 🙂

N
4.644 Beiträge seit 2004
vor 18 Jahren

Ich kenne 3 Arten einen DataReader zu schließen.

using ( SqlDataReader dr = cmd.ExecuteReader() )
{
	// ...
}
SqlDataReader dr = cmd.ExecuteReader( CommandBehavior.CloseConnection );
dr.Close();

Ob jetzt eine effizienter oder schneller ist, weiß ich nicht.
Aber es würde mich interessieren, wenn Du es testen solltest, dann poste es doch bitte hier.

B
189 Beiträge seit 2004
vor 18 Jahren

Original von SuperThoms
Allerdings will ich z.B. nur die ersten 500.000 Datensätze haben.

Dann würde ich das gleich im SQL-Statement so mit angeben:

SELECT TOP 500000 ... FROM ...

Aber bitte nicht mit WHERE id < 50000, denn niemand kann und darf garantieren, dass die IDs "lückenfrei" sind.

S
8.746 Beiträge seit 2005
vor 18 Jahren

Original von SuperThoms
Wenn man nun ein Close des DataReader sausführt, ohne dass man alle Datensätze verwendet hat, werden diese aber anscheinend trotzdem noch runtergeladen, wie man am Netzwerktraffic sehen kann. Außerdem dauert das Close() ca. 40 Sekunden.
Wenn man alle Daten runterlädt hat man diese Probleme natürlich nicht.

Die Daten, die durch deine SQL-Anweisung definiert kommen auf jeden Fall zum Client. Mit Read() werden die nur aus einem Zwischenbuffer in deine Anwendung geschaufelt. Während des Füllen des Buffers hast du aber schon Zugriff auf diejenigen Daten, die bereits angekommen sind (multi-threaded).

Dass Close() solange wartet, hängt wohl damit zusammen, dass erst der Rest der Daten der SQL-Anfrage vom Server zum Client geschaufelt werden muß. Close() wartet also die noch laufende Abfrage ab bevor es terminiert. Ob diese Implementierung wünschenswert oder zwingend ist, kann man diskutieren, ist aber das Verhalten.

Anders würde das mit einem Cursor aussehen, die gibts aber nicht in ADO.NET.

In ADO.NET 2.0 gibt es aber sowas wie BulkFetch, damit kann man sowas ähnliches realisieren wie du vorhast. Damit hast du die Steuerung darüber, wie Daten vom Server zum Client geschaufelt werden.