はじめに
タイトルの通り、EntityFrameworkパッケージをアップデートしたら特定のSQL文のみエラーとなってしまいました。
環境
- VisualStudio2019
- .NET Framework4.8
- MySQL8.0
- EntityFrameworkパッケージ 6.0.0 → 6.4.4
エラー内容
The specified cast from a materialized 'System.Int32' type to the 'System.String' type is not valid.
プログラムを起動すると上記のようなエラーが発生
結論
SQL文を実行して取得する項目とクラスのメンバの型が異なることが原因でした。
SQL文内にCASTを用い型を合わせることによりエラーが出なくなりました。
詳細
エラーが発生したのは以下のコード部分です。
SQLからデータを取得しMyClassというモデルに格納するとします。
sql.AppendLine("SELECT ")
sql.AppendLine(" ID AS id ") 'VARCHAR(255)
sql.AppendLine(",NAME AS name ") 'VARCHAR(255)
sql.AppendLine(",PRICE AS price ") 'INT(2) ←ここが原因
sql.AppendLine("FROM mytable ")
sql.AppendLine("WHERE ID = '0000' ")
'ここでエラー発生
result = entities.Database.SqlQuery(Of MyClass)(sql.ToString, params.ToArray).First()
Public Class MyClass
'クラス
Public Property id As String
Public Property name As String
Public Property price As String '←ここが原因
End Class
ここでPRICE
に注目してほしいのですが、DBテーブルとしてはINT型になっておりますがクラスの定義ではString型となっております。
そのため型の不整合が起きタイトルのようなエラーが発生しておりました。
解決策
この場合、以下のようにCASTしてString型に変換すれば不整合が発生せず正常動作します。
sql.AppendLine(",PRICE AS price ")
sql.AppendLine(",CAST(PRICE AS CHAR(255)) AS price ")
そもそも何故バージョンアップ前に動作していた?
よく考えれば動作しないはずですが、おそらくEntityFrameworkの方で型の自動変換やキャストが行われていたのではと思っています。
しかしEntityFrameworkを6.4.4にバージョンアップすることで内部的な型チェックがより厳格になったのだと考えています。
古いバージョンでは、型の自動変換やキャストが柔軟に行われていた部分が、新しいバージョンではエラーとして扱われるようになったのかもしれません。
まとめ
そもそもクラス内メンバの型の定義が間違っていたのが原因でしたが、フレームワークやライブラリのアップデートにより思わぬところでエラーが発生してしまうということを学びました。
参考