Laden...

GELÖST: MySQLDataReader unterschlägt eine Zeile der Ergebnismenge

Erstellt von conator vor 13 Jahren Letzter Beitrag vor 13 Jahren 6.909 Views
C
conator Themenstarter:in
10 Beiträge seit 2011
vor 13 Jahren
GELÖST: MySQLDataReader unterschlägt eine Zeile der Ergebnismenge

verwendetes Datenbanksystem: <mysql 5.0.51a>

Hallo zusammen,

folgender Sachverhalt (Code weiter unten):

Ich frage mit einem einem MySQLDataReader Daten ab und lese sie danach mit der klassischen while(reader.Read())-Schleife ein. Es wird aber grundsätzlich die ERSTE Zeile der Ergebnismenge unterschlagen.
Das Problem kann nicht in der Schleife liegen, denn hasRows() ist false, wenn die Ergebnismenge nur eine Zeile hat.
Woher ich weiß, dass die Ergebnisse eine Zeile mehr haben müssten? Ganz einfach: Ich prüfe das (garantiert gleiche) Statement im SQL-Developer gegen und habe eine Zeile mehr (also eine, wenn die Ergebnismenge in meinem Programm keine hat, zwei, wenns in meinem Programm eine ist etc. etc.)

Beispielstatements:


select a.ArtID, a.Name, a.Description, a.ArtGrpID, g.Name as ArtGrpName,a.FormatID, a.Width, a.Height, a.IsPrintfun, a.TSCreated, a.TSChanged, a.LabType  from cw_new_article a left join cw_new_articlegroup g on a.artgrpid=g.artgrpid where a.artid='8328';

liefert im SQL-Developer eine Zeile als Ergebnismenge (hasRows () in c# gibt mir false zurück):

8328	sticker_05	PHOTOPRODUCT	18	premiumphoto	0	52	60	0	2010-11-11 12:35:17.0	2010-11-15 17:28:16.0	30

Die folgende Abfrage gibt im SQL-Developer 14 Zeilen zurück, c# gibt mir nur 13 und unterschlägt die erste:


select a.ArtID, a.Name, a.Description, a.ArtGrpID, g.Name as ArtGrpName,a.FormatID, a.Width, a.Height, a.IsPrintfun, a.TSCreated, a.TSChanged, a.LabType  from cw_new_article a left join cw_new_articlegroup g on a.artgrpid=g.artgrpid where a.artid like '%83';

So zieht sich das durch alle Abfragen, unabhängig davon, welche Tables und Operatoren in verwende... Die Ergebnismenge in c# unterschlägt grundsätzlich die erste Zeile und hat damit eine weniger, als es sein sollte....

Hier nun der Code dazu:


                connection.Open();
                MySqlDataReader Reader = command.ExecuteReader();
                List<string[]> resultset = new List<string[]>();

                while (Reader.Read()) 
                {
                    
                    List<string> row = new List<string>();
                    for (int i = 0; i < Reader.FieldCount; i++)
                    {
                        string value = Reader.GetValue(i).ToString();
                        if (value.Length == 0) value = "N/A";
                        row.Add(value);
                        
                    }
                    resultset.Add(row.ToArray());
                }

Anmerkung: Die aufwändigen Strukturen mit den Listen lassen sich leider nicht vermeiden, weil ich die Methode universell einsetze und die Dimension der Ergebnistabelle vorher nicht feststeht.

Ich selbst suche nun seit zwei Tagen und kann kein Problem entdecken... Wäre also super, wenn jemand etwas dazu sagt, der Ahnung hat 😄

Danke im Voraus,

731 Beiträge seit 2006
vor 13 Jahren

Ho conator,

den wichtigen Teil hast Du leider ausgelassen, denn der Fehler wird durch das SQL-Statement und die (vielleicht) verwendeten Parameter entstehen.

MfG
wax

C
conator Themenstarter:in
10 Beiträge seit 2011
vor 13 Jahren

Hi Wax!

Recht hast Du! 😃 Ich habe nun mal beispielhaft zwei Statements mit Ergebnis in den Beitrag gebaut. Wobei sich das durch alle Statements zieht - unabhängig von verwendeten Tables, Operatoren, Operanden etc... MySQLDatareader gibt immer exakt eine Zeile weniger, als es sein sollte :-\

731 Beiträge seit 2006
vor 13 Jahren

Ich tippe auf den OUTER JOIN....

edit: ups, ist ja garkein OUTER JOIN. Das LEFT hat mich verwirrt. 😃

C
conator Themenstarter:in
10 Beiträge seit 2011
vor 13 Jahren

Ich tippe auf den OUTER JOIN....

Aber das Statement an sich kann's doch nicht sein, wenn's im SQL-Developer die korrekte Ergebnismenge liefert? Lediglich in C# wird eine Zeile zu wenig geliefert... Evtl. habe ich die Antwort aber auch nicht verstanden?

731 Beiträge seit 2006
vor 13 Jahren

Tritt das Problem denn auch auf wenn Du ein Query ohne JOIN absetzt?

Ich hatte so etwas auch schonmal bei unserer GUPTA DB. Das Problem war entweder ein nicht gesetzter Parameter im Command-Objekt oder eben eine Verkettung von OUTER JOIN´s die ich hatte und die bei mir auch im GUPTA-ManagementStudio ein anderes Ergebnis geliefert hatten als per .NET-Provider.

MfG
wax

C
conator Themenstarter:in
10 Beiträge seit 2011
vor 13 Jahren

Ich habe das nun mal ohne JOIN versucht. Es wird noch immer eine Zeile unterschlagen. Aber evtl. waren die Parameter des Command-Objektes ein guter Tipp. Ich werde mal gucken, was da so gesetzt werden kann und berichte, sollte da die Lösung sein...

Für Dein Feedback schon mal danke! 😃

C
conator Themenstarter:in
10 Beiträge seit 2011
vor 13 Jahren

Du weißt aber nicht zufällig, welcher Parameter das war, oder? 😃

731 Beiträge seit 2006
vor 13 Jahren

Hi,

ich meinte nicht irgendeinen Parameter, sondern einen "IDbDataParameter" den du vielleicht vergessen hast zu zuweisen.

Doch das wird bei dir wohl nicht der Fall sein, da du in deinem ersten Query ja die ID hat codiert hattest und das Problem trotzdem aufgetreten ist. Also ich bin dann mit meinem Latein am Ende.

MfG
wax

C
conator Themenstarter:in
10 Beiträge seit 2011
vor 13 Jahren

Hrm... sogar bei Minimal-SELECTs immer eine Zeile weniger. Ich werd' bescheuert 😃

Danke Dir trotzdem für die Mühe!!

1.820 Beiträge seit 2005
vor 13 Jahren

Hallo!

Ich kenne mich mit dem DataReader nicht aus, aber kann es evtl. sein, dass die while-Schleife umgedreht werden müsste, d.h. das erste Ergebnis bereits vom Reader vorgehalten wird.

Alternativ kannst du ja mal alles nicht über einen Reader sondern direkt als DataTable abrufen und vergleichen.

Nobody is perfect. I'm sad, i'm not nobody 🙁

W
955 Beiträge seit 2010
vor 13 Jahren

Hi,

hat vllt der Mysql-Treiber ein bug? Andere Version verwenden? MysqlTreiber-Source in das Projekt einbinden und mit debuggen?

W
955 Beiträge seit 2010
vor 13 Jahren

Ich kenne mich mit dem DataReader nicht aus, aber kann es evtl. sein, dass die while-Schleife umgedreht werden müsste, d.h. das erste Ergebnis bereits vom Reader vorgehalten wird.

Alternativ kannst du ja mal alles nicht über einen Reader sondern direkt als DataTable abrufen und vergleichen. Das erklärt die DataReader.HasRows-Problematik nicht.

C
conator Themenstarter:in
10 Beiträge seit 2011
vor 13 Jahren

@tom-essen:

Das dachte ich auch zuerst. Meistens liegt der Fehler ja auch da. Aber wie witte schon schreibt... Die Ergebnismenge ist wirklich kleiner. Das beweist unter Anderem der Check mit .hasRows() bei (eigentlich) einzeiligen Ergebnismengen.
Inzwischen habe ich auch welche, bei denen noch mehr Zeilen fehlen. Habe da schon nach Gemeinsamkeiten in den fehlenden / gemeinsam enthaltenen Zeilen gesucht, finde aber nichts...

witte: Ich checke nun mal andere MySQL-Treiber checken :-\

Danke schon einmal für Eure Mühe! 😃

F
10.010 Beiträge seit 2004
vor 13 Jahren

Anmerkung: Die aufwändigen Strukturen mit den Listen lassen sich leider nicht vermeiden, weil ich die Methode universell einsetze und die Dimension der Ergebnistabelle vorher nicht feststeht.

Sorry, aber das ist Blödsinn.

Wenn du eine universelle Routine haben willst, benutze einen DataAdapter und eine DataTable.
Da lässt sich dann auch ausschliessen das es am Datenholen selber liegt.

T
146 Beiträge seit 2004
vor 13 Jahren

Hallo!

Ich tippe mal einfach auf die Verarbeitung der unterschiedlichen Treiber im Bezug auf where a.artid='8328'

Da du das ja als "String" übergibst könnte es da sein, dass dein mysql Treiber diesen anders verarbeitet als das Management Studio?

Versuch mal eine Testtabelle mit nem Zahlenwert.

Ich tippe mal darauf, dass manche deiner Zeilen mit Blanks aufgefüllt werden, und du dadurch where a.artid='8328%' schreiben musst.

Wobei natürchlich where RTRIM(a.artid)='8328' die schönere Variante wäre.

C
112 Beiträge seit 2009
vor 13 Jahren

Hallo,

es gibt (oder gab) einen Bug im mySql-DataReader
http://stackoverflow.com/questions/3350153/mysqldatareader-stops-reading-after-about-4-minutes-and-returns
Und zwar meldet der Datareader, er habe alle Zeilen gelesen, allerdings ist er beim Lesen irgendwo ausgestiegen und die dabei ausgelöste Exception wird sang und klanglos verschluckt.
Ein sehr ähnliches Problem hatte ich vor einiger Zeit auch auf einer nie optimierten MySql-Datenbank, nachdem extrem viele Deletes und Inserts ausgeführt wurden. Da gab es dann mit dem DataReader ganz komische Ergebnisse, es kam quasi überhaupt nichts richtiges mehr zurück. Ich habe die Datenbank dann weggeschmissen (das ging, war eine Testdatenbank 😃)
und eine neue genommen. Danach funktionierte alles wieder reibungslos.

Grüße

Christian

C
conator Themenstarter:in
10 Beiträge seit 2011
vor 13 Jahren

@FZelle: Hast' Recht. Problematik bleibt aber bestehen 🙂

@Tomleech: Klang super, hat aber leider nicht geholfen. Wäre zu schön gewesen 😁

@Chriscolm: Danke für den Link. Habe ich in der Form selbst durch intensives Googlen nicht finden können. Scheint aber darauf hinauszulaufen, dass es einen Bug im McSqlConnector gibt und er im Ggs zu anderen Schnittstellen MySQL-DB nicht immer fehlerfrei abfragen kann (und gemeinerweise die Exception unterschlägt).

Ich werde ich da mal durcharbeiten...

Danke und Gruß an alle 😁

C
conator Themenstarter:in
10 Beiträge seit 2011
vor 13 Jahren

Übrigens unterschlägt der MySQLDataAdapter ebenfalls Zeilen (zum Teil knapp die Hälfte). Das Problem muss also defintiv in der MySQLConnection-Klasse liegen...
Das Problem tritt sogar auf, wenn man einen extra angelegten Table mit einer Spalte und wenig Daten abfragt... Strange...

C
conator Themenstarter:in
10 Beiträge seit 2011
vor 13 Jahren

Ich habe das Problem lösen können:

Mit einem alternativen Connector werden die Daten vollständig ausgelesen. Vermutlich also wirklich ein Bug im herkömmlichen MySqlConnector aus dem Hause MySql.

Den alternativen Connector gibt es hier

Die Express-Variante ist übrigens kostenlos 😁

Vielleicht hilft's ja mal dem einen oder anderen, der auf die gleiche Problematik stößt... 🙂