Разбор десятичного числа из DataReader

Я нашел обходной путь для этой ошибки, но теперь мне действительно любопытно, почему это происходит, мне было интересно, была ли у кого-нибудь еще эта ошибка.

Моя функция заключается в следующем:

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

Кто-нибудь когда-нибудь видел это раньше?

Что еще более странно, если я наберу это:

rating = decimal.Parse("4.0");

это работает нормально, 4.0 - это то, что выходит из моего DataReader.

Как я уже говорил ранее, метод TryParse работает нормально, поэтому он не мешает мне продолжать, но теперь мне действительно интересно посмотреть, есть ли у кого-нибудь ответ на него.

Ждем некоторых ответов!

Шон

ИЗМЕНИТЬ – РЕШЕНО

Метод decimal.Parse работал нормально, во второй раз, когда функция выполнялась (была в цикле), сообщение не было оценено, поэтому средство чтения данных возвращало нулевое значение. Обертывание COALESCE вокруг моего расчета в SQL решило проблему. Следовательно, почему, как вы сказали, метод tryparse не выдавал исключение, просто сохраняя значение по умолчанию от 0 до _rating.


person royse41    schedule 01.09.2009    source источник
comment
Почему бы не сделать столбец числовым, чтобы не было необходимости синтаксического анализа?   -  person John Saunders    schedule 01.09.2009


Ответы (5)


Мне это совсем не кажется странным.

Decimal.Parse() должен вызывать исключение для неверных форматов. Decimal.TryParse() не будет генерировать это исключение, а просто вернет false. Проблема в том, что вы не проверяете возвращаемое значение из Decimal.TryParse(). Я дам вам хорошие шансы на то, что Decimal.TryParse() вернет false для каждого ввода, вызывающего исключение с Decimal.Parse(), и true во всех остальных случаях. А когда Decimal.TryParse() возвращает false, выходной аргумент всегда равен "0".

Единственное возможное предостережение — локализация. Если Decimal.Parse() жалуется на, казалось бы, нормальный ввод, вы можете проверить, использует ли числовой формат (текущая культура), используемый на вашем сервере, запятую, а не десятичную дробь для отделения коэффициента от мантиссы. Но, учитывая, что ваш тест "4.0" работал нормально, я сомневаюсь, что это проблема.

Наконец, при выполнении этого преобразования из средства чтения данных следует учитывать тип исходного столбца средства чтения данных. Если уже может быть десятичной дробью. Зачем преобразовывать его в строку только для того, чтобы преобразовать обратно?

person Joel Coehoorn    schedule 01.09.2009

Вы говорите это:

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

Но на самом деле вы не проверяли возвращаемое значение TryParse. Я предполагаю, что ваш TryParse на самом деле терпит неудачу (возвращая false), поскольку decimal.Parse и decimal.TryParse используют одни и те же «правила» для синтаксического анализа, учитывая используемые вами перегрузки.

Я подозреваю, что ни один из них не работает, как вы думаете. Оба, вероятно, терпят неудачу, но TryParse не сработает.

person Reed Copsey    schedule 01.09.2009

Десятичный столбец sql не будет анализироваться в строку, которая может быть преобразована в Decimal, поэтому tryparse вернет false. Попробуйте что-то вроде этого:

 if (Convert.IsDBNull(reader["DecimalColumn"]))
     {
        decimalData = 0m;
     }
     else
     {
        decimalData = reader.GetDecimal(reader.GetOrdinal("DecimalColumn"));
     }
person TheEmirOfGroofunkistan    schedule 01.06.2012
comment
Спасибо, это было полезно, когда я переключился с загрузки набора данных (который получал исключение OutOfMemory) на использование DataReader. Я сделал это так: decimalData = (Convert.IsDBNull(reader["DecimalColumn"])) ? 0 : reader.GetDecimal(reader.GetOrdinal("DecimalColumn")); - person ScottK; 31.01.2013

Я столкнулся с той же проблемой сегодня. Попробуй это:

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

Это даст вам ту же ошибку.


Причиной этого является культура. Во французской культуре 4.0 представлен как 4,0 и, следовательно, вызывает исключение.

decimal.TryParse - это метод, инвариантный к культуре, и, следовательно, он отлично работает.

person Udeshang Parmar    schedule 26.09.2014

Измените свой TryParse на это и повторите попытку:

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

Бьюсь об заклад, это бросает ...

person Dan Diplo    schedule 01.09.2009