2009-09-01 5 views
5

Ich habe eine Ausweichlösung für diesen Fehler gefunden, aber bin jetzt wirklich neugierig, warum dies passieren würde, fragte mich, ob jemand diesen Fehler hatte.Parsing einer Dezimalstelle von einem DataReader

Meine Funktion ist wie folgt:

public void Blog_GetRating(int blogID, ref decimal rating, ref int voteCount) 
{ 
    // Sql statements 
    // Sql commands 

    if (DataReader.Read()) 
    { 
     // this line throws a 'Input string was not in a correct format.' error. 
     rating = decimal.Parse(DataReader["Rating"].ToString()); 

     // this works absolutly fine?! 
     decimal _rating = 0; 
     decimal.TryParse(DataReader["Rating"].ToString(), out _rating); 

     rating = _rating; 
    } 
} 

Wer jemals zuvor gesehen?

Was noch seltsamer ist, wenn ich diese Art:

rating = decimal.Parse("4.0"); 

, die gut funktioniert, ist die 4,0, was von meinem Datareader herauskommt.

Wie ich bereits sagte, funktioniert die TryParse-Methode gut, so dass es mich nicht davon abhält, zu tragen, aber jetzt bin ich wirklich interessiert zu sehen, ob jemand eine Antwort dafür hat.

Ich freue mich auf einige Antworten!

Sean

EDIT - GELöST

Die Decimal.Parse Methode funktioniert gut, das zweite Mal die Funktion (war in einer Schleife) ausgeführt wurde, hatte ein Post nicht so ein bewertet Nullwert wurde vom Datenleser zurückgegeben. Das Einwickeln von COALESCE um meine Berechnung in SQL hat das Problem gelöst. Daher, wie Sie sagten, hat die tryparse-Methode keine Ausnahme ausgelöst, sondern nur den Standardwert 0 auf _rating.

+1

Warum sollte die Spalte nicht numerisch sein, also müssen Sie nicht analysieren? –

Antwort

10

Das sieht überhaupt nicht komisch aus.

Decimal.Parse() ist angenommen, um eine Ausnahme für schlechte Formate zu werfen. Decimal.TryParse() wird diese Ausnahme nicht auslösen, sondern nur false zurückgeben. Der Kicker ist, dass Sie nicht den Rückgabewert von Decimal.TryParse() überprüfen. Ich gebe Ihnen wirklich gute Chancen, dass Decimal.TryParse() false für jede Eingabe zurückgibt, die eine Ausnahme mit Decimal.Parse() verursacht, und überall sonst wahr. Und wenn Decimal.TryParse() false zurückgibt, ist das Ausgabeargument immer nur "0".

Die eine mögliche Einschränkung ist die Lokalisierung. Wenn sich Decimal.Parse() über eine scheinbar normale Eingabe beschwert, könnten Sie überprüfen, ob das auf Ihrem Server verwendete Zahlenformat (aktuelle Kultur) ein Komma anstelle einer Dezimalzahl verwendet, um den Koeffizienten von der Mantisse zu trennen. Aber nachdem Ihr "4.0" -Test gut funktioniert hat, bezweifle ich, dass dies das Problem ist.

Wenn Sie diese Konvertierung vom Datenleser durchführen, sollten Sie den Quellspalte-Typ des Datenlesers berücksichtigen. Wenn möglicherweise bereits eine Dezimalzahl ist. Warum nur in eine Zeichenkette konvertieren, um sie zurück zu konvertieren?

2

Sie sagen dies:

// this works absolutly fine?! 
    decimal _rating = 0; 
    decimal.TryParse(DataReader["Rating"].ToString(), out _rating); 

Aber Sie den Rückgabewert von TryParse eigentlich nicht überprüfen. Ich würde vermuten, dass Ihr TryParse tatsächlich fehlschlägt (Rückgabe false), da dezimal.Parse und dezimal.TryParse verwenden die gleichen "Regeln" für die Analyse, angesichts der Überladungen, die Sie verwenden.

Ich vermute, dass keiner funktioniert, wie Sie denken. Beide sind wahrscheinlich versagt, aber TryParse wird nicht werfen.

0

Ihre TryParse Um dies zu ändern und versuchen Sie es erneut:

if (!decimal.TryParse(DataReader["Rating"].ToString(), out _rating)) 
{ 
    throw new Exception("Input string was not in a correct format"); 
} 

Ich wette, diese ...

1

Die SQL-dezimal wirft Spalte analysieren wird nicht eine Zeichenfolge, die zu einer Dezimal umwandeln kann, Daher wird tryparse false zurückgeben. Versuchen Sie etwas wie folgt:

if (Convert.IsDBNull(reader["DecimalColumn"])) 
    { 
     decimalData = 0m; 
    } 
    else 
    { 
     decimalData = reader.GetDecimal(reader.GetOrdinal("DecimalColumn")); 
    } 
+0

Danke, das war hilfreich, als ich vom Laden eines Datasets (das OutOfMemory-Ausnahme wurde) in die Verwendung eines DataReaders wechselte. Ich habe es so gemacht: 'decimalData = (Convert.IsDBNull (reader [" DecimalColumn "]))? 0: reader.GetDecimal (reader.GetOrdinal ("DecimalColumn")); ' – ScottK

1

Ich bin mit dem gleichen Problem heute konfrontiert. Try this:

rating = decimal.Parse("4,0"); 

Es wird Ihnen gleiche Fehler geben.


Der Grund dafür ist die Kultur. In der französischen Kultur wird 4.0 als 4,0 dargestellt, und daher löst es eine Ausnahme aus.

decimal.TryParse ist Kultur invariante Methode und daher funktioniert es gut.

+0

' decimal.TryParse ("4.0", NumberStyles.Number, CultureInfo.InvariantCulture, Bewertung); ' –