WebSurfer's Home

トップ > Blog 1   |   Login
Filter by APML

MySQL で Contoso University チュートリアル (CORE)

by WebSurfer 19. October 2021 12:22

データベースに MySQL を利用して、ASP.NET Core MVC アプリを Micorsoft のチュートリアル「ASP.NET Core MVC と EF Core - チュートリアル シリーズ」に従って作成してみました。その際に気になったこと、憶えておいた方が良さそうなことを備忘録として残しておきます。

Contoso University アプリ

チュートリアルはデータベースに SQL Server (LocalDB) を使うことを前提に書かれています。それを MySQL に代えて、チュートリアルの「1. 開始するには」から「8. コンカレンシーの競合の処理」までの手順に従って実装しました。

この記事で使った MySQL サーバーは Windows 10 にインストールしたバージョン 8.0.19 です。詳しくは先の記事「MySQL をインストールしました(その 3)」を見てください。

以下に「1. 開始するには」から「8. コンカレンシーの競合の処理」の各手順において、気になったこと、憶えておいた方が良さそうなことを書いておきます。

一番気になっていたのは「8. コンカレンシーの競合の処理」の手順の楽観的同時実行制御の実装でしたが、モデルのプロパティの定義だけ変更すれば MySQL でも可能でした。その結果が上の画像です。

(1) 開始するには

この記事では、チュートリアルに書いてあるようなプロジェクトの新規作成はせず、先の記事「MySQL で Movie チュートリアル (CORE)」で作成した既存のプロジェクトをベースに使いました。

まず Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore を NuGet からインストールします。その他の必要な NuGet パッケージはベースに使った既存のプロジェクトにインストール済です。結果は以下のようになります。

NuGet パッケージ

Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore の役割は "ASP.NET Core middleware for Entity Framework Core error pages. Use this middleware to detect and diagnose errors with Entity Framework Core migrations." だそうです。チュートリアルの「データベース例外フィルターを追加する」と関係があるようです (未確認ですが)。

Strtup.cs ファイルにある Startup クラスの ConfigureServices メソッドに SchoolContext を登録するコードを追加します。以下の通りです。

SchoolContext を登録

チュートリアルの手順「SchoolContext を登録する」に書いてあるコードは SQL Server 用で、これを MySQL 用に変更する必要がありますので注意してください。

次に appsettings.json ファイルに接続文字列を設定します。チュートリアルの例は LocalDB 用ですので MySQL 用に変更します。以下のような感じです (あくまで「感じ」です。MySQL の設定により異なります)。

接続文字列を設定

チュートリアルの「コントローラーとビューを作成する」の手順でスキャフォールディングを行う際、NuGet パッケージに Microsoft.EntityFrameworkCore.SqlServer が必要になるケースがありますので注意してください。エンティティクラスの定義によると思われます。ここ「(1) 開始するには」の手順では不要でしたが、下の「(6) 関連データの読み取り」では必要でした。

アプリを実行すると EF Code First の機能を使って、接続文字列で database=ContosoUniversity1 と指定した通り ContosoUniversity1 という名前のデータベースと、SchoolContext クラスで指定した Course, Enrollment, Student という名前のテーブルが生成されます。

さらにチュートリアルには初期データをシードするためのコードが含まれており、その通り実装すれば、最初にアプリを実行した時にコードに書かれた通り初期データが Course, Enrollment, Student テーブルに登録されます。

(2) 作成、読み取り、更新、削除の操作

チュートリアルある通りに実装してチュートリアル通りの結果が得られます。

(3) 並べ替え、フィルター、ページング、グループ化

チュートリアルある通りに実装してチュートリアル通りの結果が得られます。

(4) 移行

ここは Migration 操作を学ぶことを目的としているようです。

チュートリアルでは dotnet コマンドを使っていますが、Visual Studio を使っているならそのパッケージマネージャーコンソールを使った方が簡単だと思います。

NuGet パッケージ Microsoft.EntityFrameworkCore.Tool が必要ですが、上のステップ (1) の画像の通りインストール済みですので、このチュートリアルの操作にはパッケージマネージャーコンソールを使いました。

Drop-Database, Add-Migration, Update-Database という操作を行いますが、データベースが MySQL だから何か問題が出るということは、少なくともこのチュートリアルの操作ではありませんでした。(この後のセクション「(5) 複合データ モデルの作成」では 2 点問題がありましたが)

ベースに使った既存のプロジェクトには他の既存のコンテキストクラスが含まれています。そういう場合は、Drop-Database, Add-Migration, Update-Database 操作の際に、既存のコンテキストと区別するため、-Context SchoolContext オプションの追加が必要です。

(5) 複合データ モデルの作成

MySQL ではチュートリアルの通りにはできないということがありました。問題があったのは以下の 2 点です。

  1. Column 属性」のセクションで Student クラスの FirstMidName プロパティに付与した [Column("FirstName")] 属性。
  2. Department エンティティを作成する」のセクションで Department クラスの Budget プロパティに付与した [Column(TypeName = "money")] 属性。

いずれも Add-Migration の後の Update-Database コマンドで前者は NotImplementedException、後者は MySqlException がスローされ、MySQL のテーブルの変更・生成に失敗します。

前者は既存の Student テーブルの FirstMidName 列の名前を Migration 操作で FirstName という名前に変更しようというものです。NotImplementedException 例外がスローされるということは MySQL 用の Entity Framework にその実装がされてないということのようです。

後者は MySQL には TypeName = "money" で指定した money 型はないためのエラーです。

上記の操作に失敗で先に進めることができなくなったしまったので、やむを得ずゼロから作り直しました。Drop-Database で ContosoUniversity3 をドロップし、Add-Migration で生成された Migrations フォルダのファイルを削除し、チュートリアルに従ってコードの修正・追加を最後まで終わらせてから(途中で Migration 操作は行わないで)、最後に一気に Add-Migration, Update-Database コマンドでデータベースを生成しました。

問題となった Student クラスの FirstMidName プロパティに付与した [Column("FirstName")] 属性ですが、データベースを生成する最初の時点で付与しておけば指定した通り Student テーブルの当該列の名前は FirstName になります。チュートリアルのように最初に FirstMidName という列名で作って、後で Migration 操作で変更しようとすると、その操作に必要なメソッド等が実装されてないからか、NotImplementedException がスローされます。

Department クラスの Budget プロパティに付与した [Column(TypeName = "money")] 属性は [Column(TypeName = "decimal")] に変更が必要です。

チュートリアルの「移行を追加する」の手順に、Migrations フォルダに生成された ComplexDataModel クラスのコードに手を加えるように書かれていますが、それは先の操作でデータベースに作成済みの既存のレコードとの整合を取るためのもので、ゼロから一気に作るのであれば不要です。

(6) 関連データの読み取り

スキャフォールディング操作の際 NuGet パッケージに Microsoft.EntityFrameworkCore.SqlServer が必要になります。ちなみに「(1) 開始するには」の手順では不要でした。上の「(5) 複合データ モデルの作成」でいろいろ変更・追加したエンティティクラスの定義によると思われます。

そのため、最初のスキャフォールディング操作には失敗しますが、その際 Microsoft.EntityFrameworkCore.SqlServer が自動的に追加されますので、以下のようになっていることを確認し再度スキャフォールディングすれば成功すると思います。

NuGet パッケージの確認

上の画像の 1 番目から 4 番目のパッケージ間でのバージョンの不一致、ランタイムとのバージョンの不一致があるとスキャフォールディングに失敗することがありますので注意してください。

もう一つ、MySQL とは関係ないチュートリアルのミスですが、Courses Taught by Selected Instructor テーブルを表示する View のコードで selectedRow = "success"; となっていますが、selectedRow = "table-success"; にしないと Select しても背景色が変わらないので修正してください。

(7) 関連データの更新

チュートリアルある通りに実装してチュートリアル通りの結果が得られます。

(8) コンカレンシーの競合の処理

チュートリアルの手順では Department テーブルに rowversion (Transact-SQL) 列を追加し、それを使って楽観的同時実行制御を実装するというものです。

MySQL には rowversion はなく、それに代わるものとして timestamp というものがありますが同じではありません。.NET 側では rowversion は byte[] 型、timestamp は DateTime 型になるのですが、そのような違いがあっても Entity Framework による楽観的同時実行制御に使えるかが懸念したところです。

チュートリアルには Department クラスに byte[] 型の RowVersion プロパティを追加して Migration 操作でデータベースの Department テーブルに RowVersion 列を追加するよう書かれています。まずそこを MySQL ように変更する必要があります。

ググって見つけた記事 entity framework 6 mysql rowversion を参考に以下のプロパティ定義を使いました。

[Timestamp]
[ConcurrencyCheck]
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime TimeStamp { get; set; }

timestamp では分解能が不十分という話もあるようですが、11.3.1 DATE、DATETIME、および TIMESTAMP 型によると "DATETIME または TIMESTAMP 値には、マイクロ秒 (6 桁) までの精度で後続の小数秒部分を含めることができます" とのことですので十分ではないかと思います。なので今回は上のプロパティ定義で実装してみました。

マイクロ秒以内で同時実行が行われるケースも考えなければならないとか、どうしても分解能が気になるという場合は Better way to implement a row version with EF Core and MySQL? に紹介されている方法もありそうです。

Add-Migration, Update-Database コマンドで MySQL の Department テーブルには以下のようにそれらしい形で datetime 型の Timestamp 列が追加されます。timestamp 型でないのがちょっと気になりますが。

Department テーブル

特に気になっていたのはスキャフォールディング機能を使って Department テーブルの CRUD 用のコントローラーとビューを生成したとき TimeStamp 列を使って同時実行制御を行う機能が含まれるかということです。

結果は、SQL Server の場合と同様に、同時実行で DbUpdateConcurrencyException 例外がスローされ楽観的同時実行制御ができるようになりました。この記事の一番上の画像がその結果です。

なお、プロパティ名をチュートリアルの RowVersion から TimeStamp に変えましたので、チュートリアルの「Edit メソッドを更新する」の Edit アクションメソッドのコードで RowVersion, rowVersion となっているところは TimeStamp, timeStamp に変更が必要です。型の指定も byte[] となっているところを DateTime に変更する必要があります。

Edit 用の View のコードも同様で、「Edit ビューを更新する」のコードで RowVersion, rowVersion となっているところは TimeStamp, timeStamp に変更が必要です。

Delete については View の <input type="hidden" asp-for="RowVersion" /> の RowVersion を TimeStamp に変更します。


チュートリアルにはこの先に「9. 継承」と「10. 高度なトピック」がありますが、それはまた次の機会にということで・・・

Tags: , , , ,

CORE

MySQL で Movie チュートリアル (CORE)

by WebSurfer 3. October 2021 14:15

データベースに MySQL を利用して、Micorsoft の ASP.NET Core MVC のチュートリアル「ASP.NET Core MVC の概要」および「パート 4、ASP.NET Core MVC アプリにモデルを追加する」に従ってアプリを作る方法を書きます。

Movie アプリ

チュートリアルは、モデル(エンティティ)クラスの定義だけをプロジェクトに追加し、その後 CRUD 操作に必要な Controller、View などのコードやデータベースを Visual Studio 2019 のデザイナを利用して自動生成するというものです。初心者でも簡単に作成できるアプリながら、データベースを利用する ASP.NET Core MVC の基本的かつ重要な部分が含まれていると思います。

チュートリアルは SQL Server を使用する前提で書かれていますが、それを MySQL に変える場合はどのようにするかを以下に書きます。MySQL 本体は先の記事「MySQL をインストールしました(その 3)」に書きました既存の 8.0.19 を使います。

(1) プロジェクトの作成

チュートリアル「ASP.NET Core MVC の概要」の通り、Visual Studio 2019 のテンプレートを利用して対象のフレームワークは .NET 5.0認証「なし」の ASP.NET Core MVC アプリを作成します。

対象のフレームワークは .NET Core 3.1 でも良いですが、そうした場合は NuGet パッケージのバージョンの選び方に注意してください。間違うとスキャフォールディングでエラーになります。

また、認証を「個別のアカウント」にすると SQL Server を利用した Entity Framework 関係のパッケージがインストールされ話がややこしくなりますので、まずは認証は「なし」でやってみることをお勧めします。

(2) モデルの定義とスキャフォールディングの実行

チュートリアル「パート 4、ASP.NET Core MVC アプリにモデルを追加する」に従って、モデル(エンティティ)クラスの定義をプロジェクトに既存の Models フォルダに追加します。

using System;
using System.ComponentModel.DataAnnotations;

namespace MySqlMovie.Models
{
    public class Movie
    {
        public int Id { get; set; }
        public string Title { get; set; }

        [DataType(DataType.Date)]
        public DateTime ReleaseDate { get; set; }
        public string Genre { get; set; }
        public decimal Price { get; set; }
    }
}

次に、Microsoft.EntityFrameworkCore.Design を NuGet からインストールします。この記事では、この記事を書いた時点での最新版 5.0.10 を使いました。対象のフレームワークを .NET Core 3.1 にした場合は、Microsoft.EntityFrameworkCore.Design のバージョンは 3.1.18 にするのが良さそうです。5.0.10 を使うとスキャフォールディングでエラーになると思います。

チュートリアルの通り Visual Studio でスキャフォールディングを実行すると以下の操作が自動的に行われます。

  1. 他に必要な NuGet パッケージ(Microsoft.EntityFrameworkCore.SqlServer, Microsoft.EntityFrameworkCore.Tools, Microsoft.VisualStudio.Web.CodeGeneration.Design)の追加
  2. Data フォルダにコンテキストクラスの作成
  3. Startup.cs ファイルの ConfigureServices メソッドにコンテキストの登録
  4. appsettings.json ファイルへの接続文字列の追加
  5. CRUD 操作に必要な Controller / View 一式の生成

SQL Server の場合は上記でプロジェクトは完成ですが、MySQL を利用する場合は上の 1, 3, 4 に以下の変更を行う必要があります。

(3) NuGet パッケージの変更

スキャフォールディングで自動的に追加された NuGet パッケージ Microsoft.EntityFrameworkCore.SqlServer を削除します。 代わりに MySql.Data.EntityFrameworkCore をインストール・・・しようとしたら非推奨とのこと。 代替えパッケージが MySql.EntityFrameworkCore とのことなのでその最新版 5.0.5 をインストールしました。その結果が以下の画像です。

NuGet パッケージ

(スキャフォールディングで自動的に追加される Microsoft.EntiryFrameworkCore.Tools のバージョンは 5.0.9 ですが、Migration 操作の際ランタイムのバージョン 5.0.10 より古いという警告が出るので、上の画像では 5.0.10 に更新しています)

(4) Startup.cs ファイルの修正

スキャフォールディング操作で Startup.cs ファイルの ConfigureServices メソッドに自動的にコンテキストが登録されますが、それは SQL Server 用なので、以下のように UseSqlServer を UseMySQL に変更します。

UseSqlServer を UseMySQL に変更

コンテキストクラスの登録はコントローラーへの DI に必要です。登録してあれば、フレームワークがクライアントからの要求を受けてコントローラーを初期化する際、コンテキストクラスを初期化してコンストラクタ経由で渡してくれます。

(5) 接続文字列を MySQL 用に変更

スキャフォールディング操作で appsettings.json ファイルに接続文字列が自動生成されますが、それは SQL Server 用なので MySQL 用に変更します。

接続文字列の変更

データベース名は任意です。上の画像のように database=MySqlMovie というようにデータベース名を指定すると、Entity Framework Code First の機能を使って MySqlMovie という名前のデータベースを新たに生成し、そこに必要なテーブルを生成してくれます。

(6) Add-Migration の実行

Visual Studio のパッケージマネージャーコンソールで Add-Migration InitialCreate コマンドを実行します。結果、以下の画像の通り InitialCreate クラスが Migrations フォルダに自動生成されます。

Add-Migration の実行結果

ちなみに、InitialCreate という名前は任意に指定できます。指定した名前で xxxxx_InitialCreate.cs (xxxxx は作成日時) という名前のファイルが作成され、それに InitialCreate という名前のクラスが定義されます。

(7) Update-Database の実行

Visual Studio のパッケージマネージャーコンソールで Update-Database コマンド を実行します。これにより以下の画像の通り MySQL にデータベースが生成されます。

Update-Database の実行結果

接続文字列で database=MySqlMovie とした通り MySqlMovie という名前でデータベースが生成され、InitialCreate クラスの name: "Movie" で指定された名のテーブルが生成されています。

(8) プロジェクトの実行

上記 (7) まででアプリは完成です。プロジェクトを実行して Create 画面を表示して 2 つレコードを追加し、Index 画面でその一覧を表示したのがこの記事の一番上の画像です。

MySQL の Movie テーブルにも追加結果が反映されています。

Movie テーブルの内容

Tags: , , , ,

CORE

ASP.NET Identity で MySQL 利用 (CORE)

by WebSurfer 14. May 2020 17:33

Core 3.1 ベース(.NET Framework ではありません)の ASP.NET MVC アプリで認証に ASP.NET Identity を用い、ユーザー情報のストアに MySQL を利用するにはどうするかということを書きます。先の .NET Framework ベースの記事「ASP.NET Identity で MySQL 利用 (.NET 版)」の Core 版です。

ネットの情報ではサードパーティ製の Pomelo.EntityFrameworkCore.MySql を使ったという記事を目にしますが、ここでは NuGet でインストールできる Oracle 製の MySql.Data.EntityFrameworkCore v8.0.20 を使ってみました。

Oracle 製の MySql.Data.EntityFrameworkCore は Core に対応してないので下記ステップ「(6) プロジェクトのビルド」でエラーになったという話を聞きましたが、最新版ではそのあたりは対応されているようです。

ただし、何も問題がなかったわけではなく、最後に Update-Database でデータベース / テーブルを生成するところで "Specified key was too long; max key length is 3072 bytes" というエラーが出ます・・・が、解決は可能でした。詳しくは下のステップ「(8) Update-Database の実行」を見てください。

(1) プロジェクトの作成

Visual Studio 2019 のテンプレートを利用して ASP.NET Core 3.1 MVC アプリを作成します。認証は「認証なし」のままとしておきます。

新しい ASP.NET Core Web アプリケーションの作成

認証に「個別のユーザーアカウント」を選んでプロジェクト作成時点から ASP.NET Identity を実装しても、それを MySQL を利用するように変更できると思います。しかし、そうすると Login, Register 他の認証関係の機能は Razor Class Library (RCL) として提供され、ソースコードはプロジェクトには含まれません。

認証関係のソースコードを見たい / 修正したいことがあるでしょうから(少なくとも登録、ログインページは書き換えたくなるはず)、まず「認証なし」で作って下のステップ (2) に述べるようにスキャフォールディング機能を利用して ASP.NET Identity を実装するのがよさそうです。(「個別のユーザーアカウント」で作って、特定のページをオーバーライドすることもできるそうですが)

(2) ASP.NET Core Identity の実装

Microsoft のドキュメント Scaffold identity into an MVC project without existing authorization を参考に、スキャフォールディング機能を利用して ASP.NET Identity を実装します。

ドキュメントの通り、ソリューションエクスプローラーでプロジェクトを右クリック⇒[追加(D)]⇒[新しいスキャフォールディングアイテム(F)...]で下の画像のダイアログが開きます。

新規スキャフォールディングアイテムの追加

上のダイアログで[インストール済み]の項目から[ID]を選択し、[追加]をクリックすると以下の画像の「ID の追加」ダイアログが表示されます。

ID の追加

レイアウトページ欄にはステップ (1) で生成したプロジェクトのレイアウトページ ~/Views/Shared/_Layout.cshtml を設定します。

ソースコードが必要なファイルに[オーバーライドするファイルの選択]でチェックを入れます。(上の画像では[すべてのファイルをオーバーライド]にチェックを入れて全てのファイルを選択しています。どれを選んだらよいか分からなかったので)

[データコンテキストクラス(D)]には、+ をクリックすると表示されるデフォルトをそのまま設定しました。必要なら任意の名前に変更できます。デフォルトでは xxxxxContext の xxxxx がプロジェクト名になり、プロジェクトルート下に Areas/Identity/Data というフォルダが作られ、その中にコンテキストクラスを含むファイル xxxxxContext.cs が生成されます。

[ユーザークラス(U)]にも同様に、+ をクリックすると表示されるデフォルトをそのまま設定しました。これも任意の名前に変更できます。デフォルトでは IdentityUser を継承した xxxxxUser クラスが生成され、xxxxx がプロジェクト名になります。

[ユーザークラス(U)]に何も設定せず空白のままにしておくと IdentityUser がそのまま使われます。基本的な機能はそれで問題ないですが、もし、将来プロファイル情報を追加するようなことがあると困ることになりますので、設定しておいた方がよさそうです。

その他、NuGet での Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore の追加、Razor ページを有効にするための Startup.cs へのコードの追加を忘れないようにしてください。詳しくは上に紹介した Microsoft のドキュメントを見てください。

(3) MySql.Data.EntityFrameworkCore

NuGet で MySql.Data.EntityFrameworkCore をインストールします。この記事を書いた時点では v8.0.20 しか見つからなかったのでそれをインストールしました。

MySql.Data.EntityFrameworkCore

関連するパッケージの更新・インストールが自動的に行われます。その内容は以下の画像を見てください。

変更のプレビュー

(4) 接続文字列の変更

テンプレートで自動生成された接続文字列は appsetteins.json にありますが、それは LocalDB を利用するように設定されていますので MySQL に接続するように変更します。以下のような感じです。

接続文字列の変更

例えば、上の画像の database=coreidentity というようにデータベース名を指定すると、Entity Framework Code First の機能を使って coreidentity という名前のデータベースを新たに生成し、そこに必要なテーブルを生成してくれます。(データベース名は任意に設定できます。この記事で coreidentity としたのは単なる例です)

(5) IdentityHostingStartup.cs の修正

自動生成されれた Areas/Identity/IdentityHostingStartup.cs ファイルで、サービス登録のコードが SQL Server を使うように設定されていますが、これを MySQL を使うように変更します。以下のような感じです。

サービス登録の変更

なお、IdentityHostingStartup.cs ファイルは、上のステップ (2) のようにスキャフォールディング機能を利用して ASP.NET Identity を実装した場合に生成されるものです。プロジェクト作成の時点で認証を「個別のユーザーアカウント」とした場合は、サービス登録のコードは Startup.cs ファイルに含まれますので注意してください。

(6) プロジェクトのビルド

ここで一旦プロジェクトをビルドしてみました。以下の通り成功します。

プロジェクトのビルド

参考にさせていただいた記事「ASP.NET CoreでMySQLを利用する」ではここでエラーとなったそうです。

その記事では Core のバージョンは 2.0、MySql.Data.EntityFrameworkCore のバージョンは 8.0.6 だったそうです。この記事では Core は 3.1、MySql.Data.EntityFrameworkCore は 8.0.20 です。その差があるのでしょうか。

(7) Add-Migration の実行

パッケージマネージャーコンソールから Add-Migration CreateIdentitySchema を実行します(CreateIdentitySchema という名前は任意です。また、Core では Enable-Migration は不要になったそうです)。

Add-Migration を実行

Migrations フォルダには CreateIdentitySchema.cs ファイルが生成されます。ざっと見たところ内容は正しそうです。(ツールのバージョンが 3.1.2 でランタイムのバージョン 3.1.4 より古いという警告は出ていますが Migration には影響ないようです)

(8) Update-Database の実行

次に Update-Database を実行し、Entity Framework Code First の機能を利用して MySQL にデータベース / テーブルの生成を試みます・・・が、以下の画像の通りダメでした。

Update-Database 実行結果

メッセージを見ると AspNetUserRoles というテーブルを生成する際に "Specified key was too long; max key length is 3072 bytes" という制約のためエラーになったということのようです。

以下、少々話が長くなりますが、なぜそういうエラーになるかと、その解決方法を書きます。

データベース / テーブルは CreateIdentitySchema.cs ファイルのコードに基づいて生成されるのですが、主キーは全て、

UserId = table.Column<string>(nullable: false)

というというような maxLength が指定されない設定となります。その場合、上の画像にある通り、テーブルを生成する create 句では主キーは varchar(767) に設定されます。

varchar(767) の 767 という数字は MySQL の主キーに許容される最大バイト数で、それゆえ主キーに maxLength が指定されないと varchar(767) になるのだと思われます。

767 バイトという制限は、「InnoDBインデックスの最大キー長について」という記事によると、ある条件で 3,072 バイトまで拡張できるそうで、MySQL 5.7 以降がその条件に当てはまるそうです。この記事では MySQL 8.x を使っているのでエラーメッセージにある通り 3,072 バイトが上限になっているのだと思います。

何故 nvarchar ではなくて varchar になるのか不思議でしたが、MySQL のドキュメント 10.3.7 The National Character Set によると、"MySQL uses utf8 as this predefined character set" なのでどちらでも同じなのだそうです。ちなみに create 句で nvarchar と指定しても、生成される���は varchar になるそうです。

この記事で使用している MySQL 8.0.19 で使用されている文字コードを確認してみましたが、以下のようになっていました。

使用されている文字コード

utf8mb4 というのは、10.1.10.7 utf8mb4 文字セット (4 バイトの UTF-8 Unicode エンコーディング) によると、"utf8 という名前の文字セットは、文字あたり最大 3 バイトを使用し、BMP 文字だけを含みます。utf8mb4 文字セットは、文字ごとに最大 4 バイトを使用し、補助文字をサポートします" ということだそうです。

utf8mb4 を使用していますので、主キーに設定された varchar(767) は 767 x 4 = 3,068 バイトになります。制限の 3,072 より小さいので単独の主キーなら varchar(767) で問題ないはずです。

しかし、ASP.NET Core Identity が使うテーブルには連結主キーが設定されるものがあり、それが最大 3,072 バイトの制約を超えるため "Specified key was too long; max key length is 3072 bytes" というエラーになったということのようです。

連結主キーが設定されるテーブルは AspNetUserRoles と AspNetUserTokens です。

それらのテーブルの主キーが varchar(767) とならないよう、CreateIdentitySchema.cs ファイルの当該コードに制限 maxLength: 128 を設定してやります。以下の画像の赤枠部分を見てください。

maxLength: 128 を設定

Id フィールドには d85de5ae-a926-45cd-831a-4835034f6b79 というように書式指定された Guid の文字列が設定されますので、varchar(128) で十分なはずです(少なくとも現時点では)。

上の画像のように maxLength: 128 を設定後 Update-Database を実行すれば MySQL に ASP.NET Core Identity に必要なデータベースとテーブルが生成されます。

その後で Visual Studio から MVC アプリを動かしてユーザー登録できます。登録したユーザーはデーターベースに反映されます。もちろん登録した ID とパスワードでアプリにログインできるようになります。

Tags: , , ,

CORE

About this blog

2010年5月にこのブログを立ち上げました。その後 ブログ2 を追加し、ここは ASP.NET 関係のトピックス、ブログ2はそれ以外のトピックスに分けました。

Calendar

<<  October 2021  >>
MoTuWeThFrSaSu
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

View posts in large calendar