DataTableExtensions.AsEnumerable() выбрасывает InvalidCastException

Я использую метод DataTableExtensions.AsEnumerable для создания списка. Следующий код генерирует исключение InvalidCastException:

SaleDiscount = (i.Field<decimal>("OnSalePercentAdjustment") * i.Field<decimal>("Price")), 

Мне не нужно использовать LINQ. С помощью нескольких нажатий клавиш я могу работать с таблицей данных с помощью цикла foreach:

i.Price = Convert.ToDecimal(row["Price"]);
var saleDiscount = Convert.ToDecimal(row["SaleDiscount "]);
i.SalePrice = i.Price - (i.Price * saleDiscount );
i.SaleDiscount = i.Price - i.SalePrice;

Просто любопытно, как я могу исправить LINQ? И интересно, дает ли использование здесь LINQ какие-либо преимущества по сравнению с некоторыми сохраненными нажатиями клавиш.

2 ответа

Решение

Вы получаете исключения приведения в одном случае и никаких исключений в другом, потому что Convert.ToDecimal намного мягче, чем простой актерский состав. Исключение приведения указывает, что базовое поле не является decimal, но у него есть тип, который можно легко преобразовать в decimal,

Использовать Convert.ToDecimal внутри запроса LINQ измените код следующим образом:

SaleDiscount = (
           Convert.ToDecimal(i.Field<object>("OnSalePercentAdjustment")) *
           Convert.ToDecimal(i.Field<object>("Price"))), 

В качестве альтернативы, вы можете определить правильный тип, использовать Field<correct-type>(...) чтобы прочитать его, а затем выполнить приведение к decimal,

Это потому, что один из ваших столбцов не decimal,

Это может быть, например, intи даже он все еще числовой, и вы можете разыграть int в decimal, так как .Field<T> логика выглядит так:

return (T)((object)value);

и потому что вы можете только распаковать значение в то же самое, из которого они были упакованы:

int value = 3;
object boxedValue = value;

// works fine
int unboxedValue = (int)boxedValue;
// throws exception
double unboxedValueAsDouble = (double)boxedValue;

ты получаешь InvalidCastException, Convert.ToDecimal выглядит иначе:

return ((IConvertible)value).ToDecimal(null);

И вот почему это работает.

Другие вопросы по тегам