lycheejam's tech log

チラ裏のメモ帳 | プログラミングは苦手、インフラが得意なつもり。

EF CoreとMySQLでField 'Id' doesn't have a default valueエラーが発生

概要

ASP.NET CoreでDocker上で稼働しているMySQLをいろいろこねくり回してるんですが
タイトルのエラーが出て辛かったので対応手順のメモです。

また、本事象の回避自体はできましたが根本原因は別にありました。
本事象回避後、前回の記事のエラーが発生し対策を実施したところ今回のエラーも同時に回避可能でした。
(本記事と前回の記事のあとDBを再作成しており今回設定する設定値が初期化されたにもかかわらずエラーが発生しないことが判明したため)

前回の記事についてはこちらをご参照ください。

kitigai.hatenablog.com

目次

環境

  • MacOS Mojave Version 10.14.3
  • .Net Core SDK Version 2.2.104
  • Docker Version 18.09.2
    • Docker image : MySQL 5.7(公式)

参考サイト様

事象

Login画面に遷移し外部認証(Twitter)を実施。
その後、メールアドレスを登録するが登録した際に以下のエラーが発生する。

An unhandled exception occurred while processing the request.
MySqlException: Field 'Id' doesn't have a default value
MySqlConnector.Core.ServerSession.TryAsyncContinuation(Task<ArraySegment<byte>> task) in C:\projects\mysqlconnector\src\MySqlConnector\Core\ServerSession.cs, line 1252

MySqlException: Field 'Id' doesn't have a default value
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)

f:id:HM_Atlas:20190303025441p:plain

原因

外部認証(Twitter)を実行した際に独自のClaimをDBに登録している。
DBにデータを登録する際の動作としてAspNetUserClaimsテーブルにデータを登録する。
該当テーブルはプライマリーキーにIdカラムが存在するのだが該当のカラムはEntityFrameworkのコード上、自動採番のカラムとなっている。

根本原因としてはDBテーブルの該当カラムにauto_increment属性が付与されておらず自動採番がされなかったため主キーが抜け落ちてる状態となったためである。
しかし、この時点ではDBの設定である自動採番タイミングがEF側のコードと一致していないことが原因と疑われたためDB設定の変更を実施した。

根本原因はこちらを参照ください。

対策

MySQLsql_modeを変更します。
DockerのMySQL公式イメージをそのまま使用していたため設定値を全く変更していない状態でした。

sql_modeの確認

下記コマンドにて現在のsql_modeを確認します。

mysql> SHOW GLOBAL VARIABLES LIKE 'sql_mode';
+---------------+-------------------------------------------------------------------------------------------------------------------------------------------+
| Variable_name | Value                                                                                                                                     |
+---------------+-------------------------------------------------------------------------------------------------------------------------------------------+
| sql_mode      | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+---------------+-------------------------------------------------------------------------------------------------------------------------------------------+

sql_modeの変更

設定を変更する値についてはこちらの記事が大変わかりやすく参考になりました。

sawara.me

本件ではSTRICT_TRANS_TABLESが該当すると思われるのでSTRICT_TRANS_TABLESを設定値から外して下記のように変更します。

mysql> SET GLOBAL sql_mode = "ONLY_FULL_GROUP_BY,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION";
Query OK, 0 rows affected, 1 warning (0.00 sec)

結果確認

上記設定反映後、ログインを実施しようとすると本事象は回避できていますが
前回記事のエラーが発生しました。

雑感

送別会のあと酔っ払いながらこのエラーと格闘したんですが結局根本原因別だったって言う落ち。
酔っ払いなんだからさっさと寝ればよかった。