質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Entity Framework

Entity Frameworkは、.NET Framework 3.5より追加されたデータアクセス技術。正式名称は「ADO.NET Entity Framework」です。データベースエンジンに依存しておらず、データプロバイダの変更のみで様々なデータベースに対応できます。

.NET

.NETとは、主に.NET Frameworkと呼ばれるアプリケーションまたは開発環境を指します。CLR(共通言語ランタイム)を搭載し、入力された言語をCIL(共通中間言語)に変換・実行することが可能です。そのため、C#やPythonなど複数の言語を用いることができます。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Q&A

解決済

2回答

286閲覧

PostgreSQL環境下では正常動作してたプログラムをMySql環境へ移行したところ例外「System.InvalidCastException」が発生する。それを解決したい。

kinkin-334

総合スコア1

Entity Framework

Entity Frameworkは、.NET Framework 3.5より追加されたデータアクセス技術。正式名称は「ADO.NET Entity Framework」です。データベースエンジンに依存しておらず、データプロバイダの変更のみで様々なデータベースに対応できます。

.NET

.NETとは、主に.NET Frameworkと呼ばれるアプリケーションまたは開発環境を指します。CLR(共通言語ランタイム)を搭載し、入力された言語をCIL(共通中間言語)に変換・実行することが可能です。そのため、C#やPythonなど複数の言語を用いることができます。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

0グッド

0クリップ

投稿2024/03/23 11:37

実現したいこと

以下の事を実現したい
1.DBをPostgreSQL 16.0からMySql8.0.36へ移行する。
2.EFCoreをNpgsql.EntityFrameworkCore.PostgreSQL8.0.2からMySql.EntityFrameworkCore8.0.0へ移行する。
3.Npgsql.EntityFrameworkCore.PostgreSQL8.0.2では、動作確認が取れている既存プログラムを動かしたい

発生している問題・分からないこと

該当ソース13行目のToList()メソッド実行時に例外「System.InvalidCastException」が発生する。

上記キャスト例外が発生している箇所と思われる関連情報

SQL

1該当テーブル 2CREATE TABLE `tr_user` ( 3 `user_id` BIGINT(19) NOT NULL AUTO_INCREMENT COMMENT 'ユーザID', 4<中略> 5 `birth_day` DATE NULL DEFAULT NULL COMMENT '生年月日', 6<中略> 7 `withdrawal_date` DATE NULL DEFAULT NULL COMMENT '退会日付', 8<中略> 9) 10COMMENT='ユーザ情報' 11COLLATE='utf8mb4_0900_ai_ci' 12ENGINE=InnoDB 13AUTO_INCREMENT=18 14;

モデル

C#

1 public partial class TrUser 2 { 3 /// <summary> 4 /// ユーザID 5 /// </summary> 6 public long UserId { get; set; } 7 /// <summary> 8<中略> 9 /// 生年月日 10 /// </summary> 11 public DateOnly? BirthDay { get; set; } 12<中略> 13 /// <summary> 14 /// 退会日付 15 /// </summary> 16 public DateOnly? WithdrawalDate { get; set; } 17<中略> 18 }

DBコンテキスト

C#

1 public partial class XXXDbContext : DbContext 2 { 3 4<中略> 5 protected override void OnModelCreating(ModelBuilder modelBuilder) 6 { 7<中略> 8 modelBuilder.Entity<TrUser>(entity => 9 { 10 entity.HasKey(e => e.UserId) 11 .HasName("pk_tr_user"); 12 13<中略> 14 entity.Property(e => e.UserId) 15 .HasColumnName("user_id") 16 .HasComment("ユーザID") 17 .UseIdentityAlwaysColumn(); 18 19<中略> 20 21 entity.Property(e => e.BirthDay) 22 .HasColumnName("birth_day") 23 .HasComment("生年月日"); 24 25<中略> 26 entity.Property(e => e.WithdrawalDate) 27 .HasColumnName("withdrawal_date") 28 .HasComment("退会日付"); 29 30<中略> 31 }); 32 } 33 }

エラーメッセージ

error

1Unable to cast object of type 'System.DateTime' to type 'System.DateOnly'.

該当のソースコード

c#

1 public List<TrUser> SelectByMailAddressOrUserCd(string MailAddress) 2 { 3 var result = new List<TrUser>(); 4 DbTask.ReadOnly(db => 5 { 6 var userQuery = db.TrUsers.Where(_X => _X.UserCd == MailAddress).OrderBy(_X => _X.DeleteFlg); 7 if (!userQuery.Any()) 8 { 9 userQuery = db.TrUsers.Where(_X => _X.MailAddress == MailAddress).OrderBy(_X => _X.DeleteFlg); 10 } 11 result = userQuery.ToList(); 12 }); 13 14 return result; 15 } 16

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

類似の例外「System.InvalidCastException: Unable to cast object of type 'System.DateTime' to type 'System.DateTimeOffset'.」情報は見つけたが、開発環境.net5.0が古いのとCloseされていないので、参考にはならなかった。
[リンク内容]
https://github.com/VahidN/EFCoreSecondLevelCacheInterceptor/issues/131

.net6.0環境でのDateOnlyキャストエラーの記事についても試したが、駄目だった。
[リンク内容]
https://qiita.com/nacopon/items/10977d516e2a79b8dcc3

補足

言語:c#
開発環境:.net8.0 Entity Framework Core 8.0
データベース: MySql 8.0.36

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ikedas

2024/03/23 14:01

エラーメッセージは省略・抜粋・要約などせず、表示された内容全てを記してください (ちなみにこのコメント欄ではなく、質問文を編集して記してください)。
sazi

2024/03/24 03:39

エラーが発生するのは移行後のデータによるものですか? それとも、移行時に発生しているという事なのでしょうか? エラーメッセージからは、DateTimeと認識されるデータのDateOnlyへのキャストをサポートしていないとも取れますので。
kinkin334

2024/03/24 07:44 編集

ikedasさん コメントありがとうございます。 エラーメッセージでスタックトレースとかの情報を表示しなかったのは、ソースコードの秘匿性からです。 スタックトレースからはORマッパー(MySql.EntityFrameworkCore8.0.0)によるモデルの該当プロパティ格納時の型キャストへだと推測しています。 型キャストエラーに対処する方法を探しています。
kinkin334

2024/03/24 07:43

saziさん コメントありがとうございます。 >それとも、移行時に発生しているという事なのでしょうか? 「発生している問題」に記載していますが、該当プログラム実行時に発生しています。 EFCore6.0以降は各ライブラリdeveloperへのDateOnly型への対応が義務付けられているようです。postgresライブラリでは該当モデルへのデータ格納、DB更新は正常に行われるので、DateOnly型へ対応しています。 ライブラリ「MySql.EntityFrameworkCore8.0.0」のソースコードをGithubから入手して確認したのですが、DateOnly型対応しているように見受けられました。 しかし、ライブラリmysqlへを変更して実行すると該当箇所でキャストエラーが発生しています。 DateOnly型キャストエラーに対処する方法を探しています。
ikedas

2024/03/24 12:05 編集

ORMのコードが公知のものであるのなら、スタックトレースも (少なくとも質問者さんが独自に書いたコードの部分を除けば) 公表したところでさして問題とは思われません。 とにかく、現状ではORMの内部処理のどこかで型キャストに起因する問題が発生していることは確実と思われるので、その情報が提示されないと問題解決は難しくなりますね (絶対解決できないとは言えませんが)。
sazi

2024/03/24 11:52 編集

>>それとも、移行時に発生しているという事なのでしょうか? >「発生している問題」に記載していますが、該当プログラム実行時に発生しています。 実行した時というのは、分かっています。 データを新規に追加したときや空の状態でも起きるのかというのが問です。 メッセージからは、時刻データが含まれたデータをキャストしようとして発生しているように見えますので、 移行したデータが、時刻を含む書式で移行されている事によるものなら、プログラムではなくデータの補正という事になるかもしれませんので。
kinkin334

2024/03/24 16:13

ikedasさん このスレッドを立てた意図は型キャストエラー「Unable to cast object of type 'System.DateTime' to type 'System.DateOnly'.」の回避の手がかりを持っているなら共有して欲しいと思ったからです。 公開できる範囲でスタックトレースを以下に公開しますが、特に原因を特定できそうな情報はありませんでした。ですから、公開する必要は無いと考えました。 場所 System.Data.Common.DbDataReader.GetFieldValue[T](Int32 ordinal) 場所 MySql.Data.MySqlClient.MySqlDataReader.GetFieldValue[T](Int32 ordinal) 場所 Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext() 場所 System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) 場所 System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
kinkin334

2024/03/24 16:45

saziさん CREATE TABLE `tr_user`のスクリプトを見ていたいただければ「date型」とある通り、データには時刻は含まれていません。 ORマッパーのmysqlライブラリ内で何らかの理由により「Datetime型」誤認が発生し、モデルクラスの「DateOnly型」へ代入しようとして暗黙の型キャストにより例外が発生しているのではないかと推測しています。 ORマッパーがpostgresライブラリ且つDBがpostgresで対応するカラムがdate型の場合は、mysqlで例外が発生する場合と同じデータで正常動作しています。 これらの事象から、mysqlライブラリ内での「Datetime型」誤認の回避策があれば解決できるのではないかと考えています。
sazi

2024/03/24 19:59

回避策の為の原因を探るために、実データがどうなのかを聞いているんですが。
dodox86

2024/03/25 01:19

Entity Framework (Core)を使った.NET関連のプログラムでは、扱う人によっては実DBのテーブルのスキーマやカラムの属性を意識せずに作り続けてしまうことがあると思います。PostgreSQLのDB上の実テーブルからMySQLのDB上へはテーブル含めどのようにデータを移行したのでしょうか。C#プログラム本体のモデル上でキャスト云々の問題ではなく、EFで生成された移行元のPostgreSQL用のSQL、DbContextでは、MySQL用として使うには不整合が出ている気がします。
sazi

2024/03/25 02:54

自己解決のコメントに > 例外発生原因はEFCoreライブラリ「MySql.EntityFrameworkCore8.0.0」がDateOnly型に対応していない為でした。 とありますが、PostgresからMySQLへの移行時に型の変更をされたという事なのかが気になります。
guest

回答2

0

自己解決

自己解決しました

例外発生原因はEFCoreライブラリ「MySql.EntityFrameworkCore8.0.0」がDateOnly型に対応していない為でした。

同じ原因で嵌る人もいると思いますので、知見を共有します。

参考になるサイト
https://marcominerva.wordpress.com/2022/01/07/dateonly-and-timeonly-support-with-entity-framework-core-6-0/

以下のクラスを定義する

c#

1 public class DateOnlyConverter : ValueConverter<DateOnly, DateTime> 2 { 3 public DateOnlyConverter() : base( 4 dateOnly => dateOnly.ToDateTime(TimeOnly.MinValue), 5 dateTime => DateOnly.FromDateTime(dateTime) 6 ) 7 { 8 } 9 } 10 public class DateOnlyComparer : ValueComparer<DateOnly> 11 { 12 public DateOnlyComparer() : base( 13 (d1, d2) => d1.DayNumber == d2.DayNumber, 14 d => d.GetHashCode() 15 ) 16 { 17 } 18 }

DbContext内の該当DateOnly型プロパティマッピングヵ所にHasConversionメソッドを記述する

c#

1 entity.Property(e => e.BirthDay) 2 .HasColumnName("birth_day") 3 .HasConversion<DateOnlyConverter, DateOnlyComparer>() 4 .HasComment("生年月日"); 5

以上です

投稿2024/03/25 02:05

kinkin-334

総合スコア1

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sazi

2024/03/25 02:46

その記事は見つけていましたが、SQLServerの話であるし、文末にマイグレーションには対応していないとあります。 それで、先ずは移行後の話なのかを確認していたのです。
kinkin-334

2024/03/25 04:59

saziさん 現象を誤認されていたようですが、DBカラムは同じdate型ままにmysqlへデータ移行した上でpostgres環境下では該当モデルのDeteOnly型で正常動作してたプログラムが、ライブラリをmysqlへ変更した途端に型キャスト例外が発生したというのが質問の経緯です TimeOnly型も同様に未対応でしたので同様にSystem.InvalidCastExceptionが発生します。 該当記事のTimeOnlyConverter等の実装も必要だという事を共有します。
guest

0

とりあえず省略されているところに記載がないならuser_idに最低でもuniqueインデックスを貼ってください。もし運用上問題ないなら主キー設定しても良いでしょう

SQL

1`user_id` BIGINT(19) NOT NULL AUTO_INCREMENT COMMENT 'ユーザID', 2↓↓↓ 3`user_id` BIGINT(19) NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT 'ユーザID',

投稿2024/03/25 00:16

yambejp

総合スコア114843

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kinkin-334

2024/03/25 08:34

アドバイスありがとうございます。 主キーはuser_idへ設定済みです。 原因は特定でき、解決できました。
yambejp

2024/03/25 08:51

>主キーはuser_idへ設定済みです。 まぁ中略で重要な情報を削るからこういう行き違いが発生するんですけどね・・・
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問