14

このエラーは、プロジェクトがまだ4.0を対象としているにもかかわらず、サーバーにフレームワーク4.5をインストールしたことが原因のようです。

4.5はCLRを置き換え、tinyint型のオブジェクトをintにアンボックスすることに変更があったようです。これは4.0では機能していましたが、4.5をインストールした後は機能しませんでした。

============================================

答える前に質問全体を読んでください、ほとんどの現在の答えは私が尋ねている質問に答えません。

今日、SQLのtinyintからintを使用したintへのキャストでエラーが発生しました

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

これは、何も変更せずに数年間製品に含まれている古いコードであり、昨日まで機能しています。(そして、それは正確なコードではなく、コンテキストを示すのに十分です)

===更新

正確なエラーメッセージは次のとおりです。「指定されたキャストは無効です!」そして最後の行

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

は、変数名と列名のみが変更されたエラーをキャストするコードからの正確な行です。

また、データベース列はtinyintで、デフォルト値は0で、インデックスやその他の制約はありませんでした。

===更新を終了します

===アップデート2

Henk Holtermanは、彼の回答で、4.0用に特別にコンパイルされたプロジェクトでもFW 4.5が4.0のCLRを置き換え、これにより既存の4.0の動作がこのようにリモートで変更される可能性があることを通知しました。

私はこれをもう少し開いたままにしますが、彼の答えはこれまでで最も有望です:D===終了

数週間前にフレームワーク3.5から4.0に変更しましたが、これが発生したのは昨日の午後だけでした。昨日の朝、同じコード(再コンパイル後も)は時計仕掛けのように機能しました。

なぜこれが以前は機能していたのか、現在は機能していないのかについて誰かが知っていますか?

マイクロソフトは、暗黙の変換を削除する内部的な変更を行ったことがありますか、それとも以前に純粋な魔法で機能したことがありますか?

データベースの列をintに変更することで解決しましたが、今のところ失敗の原因が何であるかについてはまだ興味があります。

===アップデート3

これを完了するためだけに。

フレームワーク間の変化を見つけました。アップデートで、Microsoftはボクシングとアンボクシングの方法を変更しました。これにより、バイトからintへの暗黙のキャストが発生し、データテーブルにあるため、バイトがボックス化されたときに古いFWが失敗しました。

ボックス化されていないバイトは4.5で暗黙的にintにキャストされますが、ボックス化されたバイトは暗黙的にキャストできないジェネリックオブジェクトです。

そうではありません。これは3.5SP1で変更されたため、SP1への更新が4.0更新に含まれていない限り、FW4.0も失敗するはずです。これはまだ答えられていません:)

これに関するMSからのチケットです;) https://connect.microsoft.com/VisualStudio/feedback/details/766887/casting-tinyint-from-sql-datarow-to-int-no-longer-possible

4

5 に答える 5

26

それは決してうまくいかなかったはずです。これにより、フレームワークで何かが修正された可能性があります。

C#の問題:

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の一部を置き換えます。

于 2012-10-10T12:37:16.310 に答える
6

TinyInt型はデフォルトで、それ自体がintにキャスト可能なバイト型を返しますが、dbのTinyInt型はそうではないので、これを試してください。

(int)(byte)datarow["tinyintcolumn"];
于 2012-10-10T12:35:38.387 に答える
2

タイプだtinyintから。Byteリストは次のとおりです。LIST

byte arrayに変換する必要がありますint。ここでの解決策:解決

于 2012-10-10T12:36:46.197 に答える
2

答えを他の接続ライブラリで使用できるようにするために、私はこれを共有します。MariaDbとMySqlコネクタ/ネットを使用しているため、選択した回答が直接機能しませんでした。したがって、最初に、返されたsql tinyintフィールドのC#データ型を見つける必要があります。

次に例を示します。

MySqlHelper.ExecuteDataset()を使用し、クエリを実行してtinyint(4)列をフェッチしています。

SELECT tinyintcolumn FROM datatable WHERE ...

「指定されたキャストが無効です!」というメッセージが表示されました。SQLクエリでキャスト関数を使用した場合でも例外:

SELECT CAST(tinyintcolumn AS int) ...

私は最初にここや他の場所で提案されたすべてを試していましたが、最後にうまくいったのは、c#のフィールドのタイプを見つけることです:

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];
于 2015-10-26T09:45:00.220 に答える
0

SQLのtinyintのサイズは1バイト(8ビット)だと思うので、「int」(32ビット)ではなく「byte」にキャストしてみてください。しかし、データベースでtinyintを使用していないため、これを試していません。

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

また、データベースtinyintcolumnの列がNULL可能である場合は、値をキャストするときにそれも考慮する必要があります。

于 2012-10-10T12:43:09.460 に答える