Ошибка при запуске крошечного int int

Эта ошибка выглядит так, что она была вызвана установкой фреймворка 4.5 на сервере, хотя проект по-прежнему нацелен на 4.0.

4.5 заменяет CLR и похоже, что он имеет изменения при распаковке объекта типа tinyint в int. Это работало в 4.0, но не после установки 4.5.

============================================р >

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

Сегодня мы получили ошибку в листинге из tinyint в sql для int с использованием

Daterow datarow = GetOneDatarow(connection,
                         "SELECT tinyintcolumn FROM table1 WHERE id = 4");
int i = (int)datarow["tinyintcolumn"];

Это старый код, который был в продукте в течение нескольких лет без каких-либо изменений, и он работает до вчерашнего дня. (И это не точный код, достаточно, чтобы показать контекст)

=== UPDATE

Точное сообщение об ошибке: "Указанный приведение недействительно!" и последняя строка

int i = (int)datarow["tinyintcolumn"];

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

И столбец базы данных был tinyint со значением по умолчанию 0, без индексов или других ограничений.

=== Окончательное обновление

=== UPDATE 2

Хенк Холтерман в своем ответе сообщил мне, что FW 4.5 заменяет CLR 4.0 даже для проектов, составленных специально для 4.0, и это может удаленно изменять существующее поведение 4.0 именно так.

Я буду держать это открытым некоторое время больше, но его ответ является наиболее перспективным до сих пор: D === Конец

Мы изменили с рамки 3.5 до 4.0 несколько недель назад, но только вчера после перекомпиляции, что это произошло, вчера утром такой же код (даже после перекомпиляции) работал как часовой механизм.

Есть ли у кого-нибудь идеи о том, почему это работает раньше и не работает сейчас?

Развернулся ли Microsoft под капотом, который удалил неявное преобразование или он работал с чистой магией раньше?

Мы решили это, изменив столбец базы данных на int, но мне все еще интересно, что могло бы привести к его сбою прямо сейчас.

=== UPDATE 3

Только для этого.

Я нашел изменение между фреймворками. В обновлении Microsoft изменила способ бокса и распаковки. Это вызвало неявное преобразование из байта в int, которое старший FW сделал с ошибкой, когда байт был помещен в бокс, так как он находится в datatable.

Unboxed byte будет в 4.5 быть неявным образом перенесен в int, но байт в штучной упаковке является универсальным объектом, который не может быть неявным.

Нет, это было изменено в 3.5 SP1, поэтому наш FW 4.0 также должен был сбой, если обновление до SP1 не было в обновлении 4.0. Это еще не ответило:)

Вот билет от MS на этом;) https://connect.microsoft.com/VisualStudio/feedback/details/766887/casting-tinyint-from-sql-datarow-to-int-no-longer-possible

Ответ 1

Он никогда не должен был работать. Скорее всего, что-то было исправлено в рамках.

Проблема в С#:

byte b = 3;       // TinyInt is a Byte
object o = b;     // DataRow[i] is an object
int i = (int)o;   // invalid cast

Исправление:

int i = (byte)datarow["tinyintcolumn"];

И из комментария ниже:

Мы установили его, но этот проект не скомпилирован в сторону 4.5, только до 4.0,... может быть так?

Да, фреймворк 4.5 заменяет части 4.0.

Ответ 2

Тип TinyInt будет по умолчанию возвращать тип байта, который сам может быть спрятан для int, но тип TinyInt не существует, поэтому попробуйте следующее:

(int)(byte)datarow["tinyintcolumn"];

Ответ 3

Потому что tinyint - это тип Byte. Вот список: LIST

Вам нужно преобразовать byte array в int. Решение здесь: РЕШЕНИЕ

Ответ 4

Чтобы сделать ответ полезным для других библиотек подключений, я разделяю это. Я использую коннектор MariaDb и MySql/Net, поэтому выбранный ответ не работал у меня напрямую. Поэтому сначала вам нужно узнать тип данных С# для возвращаемого поля sql tinyint.

Вот пример:

Я использую MySqlHelper.ExecuteDataset() и выполняю запрос для извлечения столбца tinyint (4):

SELECT tinyintcolumn FROM datatable WHERE ...

Я получаю "Указанный приказ недействителен!" исключение, даже если я использовал функцию броска в SQL-запросе:

SELECT CAST(tinyintcolumn AS int) ...

Сначала я попробовал все предлагаемые здесь и в другом месте, но, наконец, что сработало, это выяснить, что такое тип поля в С#:

DataTable datatable MySqlHelper.ExecuteDataset(connString, sql).Tables[0];
DataRow datarow = datatable .Rows[0];
Type datatype = datarow.ItemArray[0].GetType();

Результат: System.SByte! Так что для меня это прекрасно, чтобы использовать одно из следующих:

SByte sbTinyint = datarow.Field<SByte>(0);
SByte sbTinyint2 = (SByte)datarow.ItemArray[0];
int iTinyint = (int)datarow.Field<SByte>(0);
int iTinyint2 = (int)(SByte)datarow.ItemArray[0];

Ответ 5

Я считаю, что размер SQL tinyint равен 1 байту (8 бит), поэтому попробуйте перевести его в "байт" вместо того, чтобы перевести его в "int" (это 32 бита). Но я не пробовал это, так как я не использую tinyint в моей базе данных.

byte i = (byte)datarow["tinyintcolumn"];

Кроме того, если ваш столбец в базе данных tinyintcolumn имеет значение NULL, вам также необходимо принять это во внимание при добавлении значения.