Avatar billede fbisen Nybegynder
03. april 2010 - 08:21 Der er 23 kommentarer og
2 løsninger

MySQL: command.executeReader() returnerer null

Hej Eksperten.

Jeg har et meget underligt spørgsmål som jeg simpelthen ikke kan finde svar på. Egentlig synes jeg det burde være let, men jeg får en fejl der ikke giver mening.

Følgende kode bliver kørt:

MySqlCommand offsetCommand = connection.CreateCommand();
offsetCommand.CommandText = "SELECT FLOOR(RAND() * COUNT(*)) AS 'offset' FROM urls WHERE lastcrawled is NULL AND tld = 'dk' AND localpath = '';";
           
MySqlDataReader offsetReader = offsetCommand.ExecuteReader();
if (!offsetReader.Read()) <--- NullReferenceException her
  throw new Exception("There should be a result here!");

Jeg er 100% på at der er en forbindelse og at min query genererer output. Det underlige er at denne fejl kun sker sjældent.
Ofte kører mit program igennem denne stump af kode 50-100 gange før fejlen sker.

Forbindelsen bliver brugt mange gange. Det er ikke en forbindelse jeg åbner for hver command jeg skal køre.

Jeg har fundet følgende som skulle løse problemet
( http://www.dotnet247.com/247reference/msgs/22/114651.aspx )
GC.Collect();
GC.WaitForPendingFinalizers();
Begrundelsen er at der skulle være en fejl i .NET's måde at allokere hukommelse - Ingen annelse om det er rigtigt, men det virker i hvert fald ikke.

Jeg synes fejlen er utrolig underlig, det burde jo bare virke!
Er der nogen der ved hvad jeg skal gøre?
Avatar billede arne_v Ekspert
03. april 2010 - 14:03 #1
Det med manuelt GC kald er noget sludder, saa ingen overraskelse i at det ikke virker.
Avatar billede arne_v Ekspert
03. april 2010 - 14:06 #2
Maa vi se hele den relevante kode snippet. Det postede ligner noget der er klippet her og der. Og nogen gange gemmer problemet sig i det som ikke er med.
Avatar billede fbisen Nybegynder
04. april 2010 - 11:55 #3
Her er hele metoden:

==========
public Link getNextLinkToCrawl()
{
    // What are we selecting after?
    const string whereClause = " WHERE lastcrawled is NULL AND tld = 'dk' AND localpath = ''";

    // First find out what row we would like to fetch
    MySqlCommand offsetCommand = connection.CreateCommand();
    offsetCommand.CommandText = "SELECT FLOOR(RAND() * COUNT(*) AS 'offset' FROM urls" + whereClause + ";";
   
    MySqlDataReader offsetReader = offsetCommand.ExecuteReader();

    //@TODO HELP! offsetReader is sometimes null here. How the hell can that happen???
    if (!offsetReader.Read())
        throw new Exception("There should be a result here!");

    int offset = offsetReader.GetInt32("offset");
    // Close the reader
    offsetReader.Close();

    // Fetch the row!
    MySqlCommand rowCommand = connection.CreateCommand();
    rowCommand.CommandText = "SELECT scheme, userinfo, host, tld, port, localpath, postvariables FROM urls" + whereClause + " LIMIT " + offset + ", 1;";
    MySqlDataReader reader = rowCommand.ExecuteReader();

    Link toReturn = readerToLink(reader);

    // Close reader before returning
    reader.Close();

    return toReturn;
}
=========
Avatar billede arne_v Ekspert
04. april 2010 - 14:24 #4
Der er noget mystisk her.

offsetCommand.CommandText = "SELECT FLOOR(RAND() * COUNT(*) AS 'offset' FROM urls" + whereClause + ";";

burde vel egentligt give fejl p.g.a. manglende ) og fordi der er brugt '' fremfor ``
Avatar billede fbisen Nybegynder
04. april 2010 - 18:24 #5
En query som:
SELECT scheme, userinfo, host, tld, port, localpath, postvariables FROM urls WHERE lastcrawled is NULL AND tld = 'dk' AND localpath = '' LIMIT 2, 1;

og
SELECT FLOOR(RAND() * COUNT(*)) AS 'offset' FROM urls WHERE lastcrawled is NULL AND tld = 'dk' AND localpath = '';

virker fint både i MySQL Query Browser og C#. Der manglede dog en parantes (som jeg havde glemt åbenbart. Men den var der før)
Avatar billede fbisen Nybegynder
04. april 2010 - 18:46 #6
Her er et link til hele filen. Så er det muligt at se hvordan det hele omkring Connection ser ud.

http://dl.dropbox.com/u/374549/MySqlLinkResultSaver.cs

Nu ser det ud til at jeg får fejl i min hjælpefunktion (readerToLink). Dette giver stadig ikke mening.
Avatar billede arne_v Ekspert
04. april 2010 - 19:25 #7
Hm.

Hvilken version af MySQL Connector for .NET bruger du ?
Avatar billede fbisen Nybegynder
04. april 2010 - 20:00 #8
mysql-connector-net-6.2.2-noinstall (.NET & MONO).

Jeg kører på Windows 7 med MySQL 5.1.45-community som Server.
Jeg bruger .NET & MONO da min applikation også skal køre på Linux.
Avatar billede arne_v Ekspert
04. april 2010 - 20:16 #9
Jeg spurgte fordi jeg undrede mig over at du bruger "@xxxx" for parametre.

Man plejer at bruge "?xxxx".
Avatar billede arne_v Ekspert
04. april 2010 - 20:21 #10
Du kunne også prøve at Close/Dispose din command hver gang.
Avatar billede fbisen Nybegynder
04. april 2010 - 20:50 #11
Grunden til at jeg bruger @ er denne kommentar i MySQL connector hjælpefilen til Command.
"Note: Using the '@' symbol for paramters is now the preferred approach although the old pattern of using '?' is still supported. Please be aware though that using '@' can cause conflicts when user variables are also used."

Man kan ikke Close Command. Man kan godt dispose, men dette gøres ikke i hjælpefilen. Til gengæld lukker de forbindelsen.

Jeg prøver at kalde Dispose hver gang nu, og så ser jeg hvad der sker.
Avatar billede fbisen Nybegynder
04. april 2010 - 20:55 #12
Nope. Samme problem. Jeg har lagt den nyere version op på

http://dl.dropbox.com/u/374549/MySqlLinkResultSaver.cs
Avatar billede arne_v Ekspert
04. april 2010 - 21:55 #13
Hvilken linie i readerToLink giver hvilken fejl?
Avatar billede fbisen Nybegynder
05. april 2010 - 09:30 #14
Første linje i ReaderToLink if(reader.Read())

Fejlen kummer da reader er Null -> Så det er en NullReferenceException der bliver smidt.

Det underlige er hvordan en Null værdi er kommet dertil -> command.ExecuteReader() nævner intet om at Null kan returneres, eller hvilken årsag der kunne være dertil.
Avatar billede arne_v Ekspert
06. april 2010 - 01:26 #15
Dybt mystisk. Jeg har nu kigget på kilde koden for MySqlCommand ExecuteReader. Den bør aldrig returnere null.
Avatar billede arne_v Ekspert
06. april 2010 - 01:28 #16
Jeg kan ikke se anden udvej end at du må igang med at steppe dig gennem både din egen kode og MySqlCommand.ExecuteReader i debuggeren for at finde ud af hvad der sker.
Avatar billede arne_v Ekspert
06. april 2010 - 01:29 #17
Du kører ikke flere tråde som bruger samme instans af den klasse ?
Avatar billede fbisen Nybegynder
06. april 2010 - 08:02 #18
Jeg kører kun én tråd i mit program. Jeg har til gengæld kørt flere instancer af programmet på samme tid - men jeg kan ikke forestille mig at kørslen af programmet flere gangen skulle gøre noget.

Jeg ville gerne debugge det, men problemer er at det sker ikke hver gang - faktisk sjældent. Derfor er det ikke muligt at teste. Det sker dog ofte nok til at programmet ikke kan køre i meget mere end ½time.

Jeg er lidt lamslået over din konklusion om at Null ikke kan returneres, for hvor skulle værdien Null så komme fra?
Avatar billede arne_v Ekspert
06. april 2010 - 19:19 #19
Det er jo det store spoergsmaal.  Men som jeg laeser koden vil den enten returnere et valid objekt eller smide en exception.
Avatar billede arne_v Ekspert
06. april 2010 - 19:20 #20
Er det hele oversat for debug saaledes at man kan stole paa linienumre i trace?
Avatar billede fbisen Nybegynder
06. april 2010 - 20:49 #21
Hmm. Jeg har faktisk kørt lidt release. Men kørte den lige i debug -> Samme svar.

Jeg har nu gjort sådan at der laves en ny forbindelse hver gang jeg laver en command. Dette ser ud til at virke. Jeg føler bare det er dumt, da jeg jo egentlig ikke har behov for at åbne/lukke forbindelser hele tiden.

Men det ser ud til at virke :S
Avatar billede arne_v Ekspert
07. april 2010 - 01:41 #22
Da MySqlConnection ligesom andre ADO.NET providere bruger en connection pool, saa koster det ikke noget at aabne og lukke hele tiden.
Avatar billede fbisen Nybegynder
07. april 2010 - 07:34 #23
Det er da lidt underligt jeg så ikke få fejlen længere. Et eller andet må den jo gøre på en connection.Close() som rydder op og gør fejlen ikke kommer. Tak for denne info, det gør at løsningen er mere iorden i mit hoved :)
Avatar billede fbisen Nybegynder
22. august 2010 - 10:27 #24
Tak for hjælpen arne, jeg synes vi skal dele point - ligger du også et svar?
Avatar billede arne_v Ekspert
22. august 2010 - 10:32 #25
ok
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester