简体   繁体   中英

Parsing a decimal from a DataReader

I found a workaround for this error, but am now really curious as to why this would be happening, was wondering if anyone else has had this error.

My function is as follows:

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;
    }
}

Anyone ever seen that before?

What's even weirder is if i type this:

rating = decimal.Parse("4.0");

that works fine, the 4.0 is what is coming out from my DataReader.

As I said previous, the TryParse method works fine so it's not stopping me from carrying, but now I'm really interested to see if anyone has an answer for it.

Looking forward to some replies!

Sean

EDIT - SOLVED

The decimal.Parse method was working fine, the second time the function was running (was in a loop), a post hadn't been rated so a null value was being returned by the data reader. Wrapping COALESCE round my calculation in SQL solved the problem fine. Hence why, as you said, the tryparse method wasn't throwing an exception, just keeping the default of 0 to _rating.

That doesn't look weird to me at all.

Decimal.Parse() is supposed to throw an exception for bad formats. Decimal.TryParse() will not throw that exception, but instead just return false. The kicker is that you're not checking the return value from Decimal.TryParse() . I'll give you real good odds that Decimal.TryParse() returns false for every input that causes an exception with Decimal.Parse() , and true everywhere else. And when Decimal.TryParse() returns false, the output argument is always just "0".

The one possible caveat is localization. If Decimal.Parse() is complaining about a seemingly normal input, you might check if the number format (current culture) used on your server uses a comma rather than a decimal to separate the coefficient from the mantissa. But given your "4.0" test worked fine, I doubt this is the problem.

Finally, when doing this conversion from data reader you should consider the source column type of the data reader. If might already be a decimal. Why convert it to a string only to convert it back?

You are saying this:

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

But you didn't actually check the return value of TryParse. I would guess that your TryParse is actually failing (returning false), since decimal.Parse and decimal.TryParse use the same "rules" for parsing, given the overloads you're using.

I suspect that neither is working as you think. Both are probably failing, but TryParse won't throw.

The sql decimal column won't parse to a string that can convert to a Decimal, so tryparse will return false. Try something like this:

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

I am facing same problem today. Try this:

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

It will give you same error.


The reason behind this is the culture. In the French culture, 4.0 is represented as 4,0, and hence it throws an Exception.

decimal.TryParse is culture invariant method and hence it works fine you.

Change your TryParse to this and try again:

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

I bet this does throw...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM