Ошибка при запуске крошечного 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, вам также необходимо принять это во внимание при добавлении значения.