概要
.NET CoreでDocker上で稼働しているMySQLをいろいろこねくり回してるんですが
タイトルのエラーが出て辛かったので対応手順のメモです。
https://twitter.com/Lychee_jam/status/1101414186892984320 🔗
目次
環境
- MacOS Mojave Version 10.14.3
- .Net Core SDK Version 2.2.104
- Docker Version 18.09.2
- Docker image : MySQL 5.7(公式)
参考サイト様
- http://d.hatena.ne.jp/puchiban/20110524 🔗
- https://stackoverflow.com/questions/44744943/auto-increment-is-not-working-on-model 🔗
- https://docs.microsoft.com/ja-jp/ef/core/miscellaneous/cli/dotnet 🔗
事象
Login
画面に遷移し外部認証(Twitter)を実施。
その後、メールアドレスを登録するが登録した際に以下のエラーが発生する。
An unhandled exception occurred while processing the request.
MySqlException: Duplicate entry '0' for key 'PRIMARY'
MySqlConnector.Core.ServerSession.TryAsyncContinuation(Task<ArraySegment<byte>> task) in C:\projects\mysqlconnector\src\MySqlConnector\Core\ServerSession.cs, line 1252
MySqlException: Duplicate entry '0' for key 'PRIMARY'
MySql.Data.MySqlClient.MySqlDataReader.ActivateResultSet(ResultSet resultSet) in C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlDataReader.cs, line 81
DbUpdateException: An error occurred while updating the entries. See the inner exception for details.
Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
原因
外部認証(Twitter)を実行した際に独自のClaimをDBに登録している。
DBにデータを登録する際の動作としてAspNetUserClaims
テーブルにデータを登録する。
該当テーブルはプライマリーキーにId
カラムが存在するのだが該当のカラムはEntityFrameworkのコード上、自動採番のカラムとなっている。
しかし、DBテーブルの実態としてはauto_increment
属性が付与されておらず自動採番がされなかったため主キーが抜け落ちてる状態となり上記のエラーが発生した。
※該当カラムが自動採番で有ることは確認済み。
EntityFrameworkのスナップショットだとオートインクリメント付いてんだけどな〜 // https://t.co/ngkui2F6tS<int>("Id").ValueGeneratedOnAdd();
— あとらす (@Lychee_jam) 2019年3月2日
また、本事象が発生した原因はWindows端末のVisualStudio 2017にてプロジェクトを作成した後
GitHub経由でMac環境へ共有し開発用DBとしてDocker上で稼働するMySQLを使用したが
Oracle公式の接続プロバイダからOSSの接続プロバイダであるPomeloへの切り替えなど多数の変更があったためMigrationの記録がうまくDBに反映されなかったためと推察される。
- 該当のテーブル
mysql> DESC TODOAPP.AspNetUserClaims;
+------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+-------+
| Id | int(11) | NO | PRI | NULL | |←auto_incrementが付与されていない
| UserId | varchar(767) | NO | MUL | NULL | |
| ClaimType | text | YES | | NULL | |
| ClaimValue | text | YES | | NULL | |
+------------+--------------+------+-----+---------+-------+
対策
結論としてはDBテーブルを作成し直す。
(今回は開発用DBであるため碌なデータがないのでデータバックアップ等には触れない。)
下記手順をプロジェクトディレクトリにて実行する。
DBの削除
$ dotnet ef -v database drop
Migration(履歴)の削除
migrationの一覧を確認する。
$ dotnet ef migrations list
migration(履歴)を削除する。
※Migrationの件数分、繰り返す
一括削除の方法はわからなかったので誰か教えてください。
(ファイルを手動で削除して__MigrationHistory
のデータも手動削除してやればよかったのかな?)
$ dotnet ef migrations remove -v -f
Database Update
DatabaseUpdateをかけてテーブルの再作成を実行。
$ dotnet ef migratoions add init
$ dotnet ef database update
結果確認
DBにてテーブルを確認すると属性が付与されていることが確認できます。
また、画面でもエラー無く操作できることが確認できます。
mysql> select * from TODOAPP.AspNetUserClaims;
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| Id | int(11) | NO | PRI | NULL | auto_increment |
| UserId | varchar(255) | NO | MUL | NULL | |
| ClaimType | longtext | YES | | NULL | |
| ClaimValue | longtext | YES | | NULL | |
+------------+--------------+------+-----+---------+----------------+
雑感
多分、Oracle公式の接続プロバイダ使ってるときにMigration一回したんだけど
それでうまく属性が反映されてなかったっぽい。