WebSurfer's Home

トップ > Blog 1   |   Login
Filter by APML

ASP.NET Identity で MySQL 利用 (.NET 版)

by WebSurfer 6. May 2020 21:43

.NET Framework 版(Core 版ではありません)の ASP.NET Identity でユーザー情報のストアに MySQL を利用するにはどうするかということを書きます。(Core 3.1 版は別の記事「ASP.NET Identity で MySQL 利用 (CORE 版)」を見てください)

参考にさせていただいたのは「ASP.NET MVC + MySQL で開発環境構築」という記事です(以下、参考記事と書きます)

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

Visual Studio 2019 のテンプレートを利用して .NET Framework 版の ASP.NET MVC5 アプリのプロジェクトを自動生成します。

新しい ASP.NET Web アプルケーションを作成する

認証に「個人ユーザーアカウント」を選ぶと ASP.NET Identity を使ったクッキーベースの認証システムが実装され、Entity Framework Code First の機能を使って LocalDB (SQL Server) にユーザー情報を保持するためのデーターベースを作るコードが生成されます。

それを LocalDB (SQL Server) ではなくて MySQL にユーザー情報を保持するためのデーターベースを作り、それを利用するように変更します。

(2) 参照設定

ソリューションエクスプローラーで参照を右クリックして MySql.Data と MySql.Data.EntityFramework を参照に追加します。下の画像を見てください。

参照設定

先の記事「MySQL をインストールしました(その 3)」で書きましたように MySQL 8.0.19 をインストールしており、その時同時にインストールした Connector/NET 8.0.19 に含まれる MySql.Data, MySql.Data.EntityFramework を使うことにしました。

参考記事では NuGet で MySql.Data.Entity をインストールしたと書いてありましたが、NuGet にあるのは今でもバージョンが古いようです。

(3) 接続文字列の変更

テンプレートで自動生成された web.config の接続文字列は LocalDB を利用するように設定されていますので、それを MySQL に接続するように変更します。

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

<add name="DefaultConnection"
    connectionString="server=localhost;user id=root;password=*****;
    database=identity"
    providerName="MySql.Data.MySqlClient" />

(4) Enable-Migrations

上記 (3) の設定の後、Enable-Migrations を実行すると以下のエラーになると思います。

"ADO.NET プロバイダーに、不変名が 'MySql.Data.MySqlClient' の Entity Framework プロバイダーがありません。アプリケーションの構成ファイルの "entityFramework" セクションにプロバイダーが登録されていることを確認してください"

それを解決するためには、エラーメッセージに応じて、自動生成された web.config の entityFramework/providers セクションに以下のコードを追加します。

<provider 
  invariantName="MySql.Data.MySqlClient" 
  type="MySql.Data.MySqlClient.MySqlProviderServices, 
        MySql.Data.EntityFramework,Version=8.0.19.0, Culture=neutral, 
        PublicKeyToken=c5687fc88969c44d" />

NuGet で MySql.Data.Entity をインストールした場合は web.config への上記の provider の追加は NuGet が面倒を見てくれるようです。

上のコードを web.config に追加した後 Enable-Migrations を実行すると Migrations フォルダに Configuration.cs ファイルが生成されているはずです。

(5) Add-Migration

Add-Migration Initial を実行します(Initial という名前は任意です)。そうすると、参考記事と同様に以下のエラーになると思います。

"プロバイダー 'MySql.Data.MySqlClient' で MigrationSqlGenerator が見つかりませんでした。対象の移行構成クラスで SetSqlGenerator メソッドを使用して、追加の SQL ジェネレーターを登録してください"

エラーメッセージに従って Configuration.cs に手を加えます。以下のコードのコメントで「追加」としている部分がそれです。

namespace Mvc5AppIdentityMySql.Migrations
{
  using System;
  using System.Data.Entity;
  using System.Data.Entity.Migrations;
  using System.Linq;

  // 追加
  using MySql.Data.EntityFramework;

  internal sealed class Configuration : 
    DbMigrationsConfiguration<Mvc5AppIdentityMySql.Models.ApplicationDbContext>
  {
    public Configuration()
    {
      AutomaticMigrationsEnabled = false;

      // 追加
      SetSqlGenerator("MySql.Data.MySqlClient", 
                      new MySqlMigrationSqlGenerator());
    }

    protected override void Seed(
      Mvc5AppIdentityMySql.Models.ApplicationDbContext context)
    {
    }
  }
}

エラーメッセージの SetSqlGenerator メソッドというのは DbMigrationsConfiguration クラスの SetSqlGenerator(String, MigrationSqlGenerator) メソッド です。これをコンストラクタに追加します。

SetSqlGenerator メソッドの第 1 引数には MySQL のプロバイダ名 "MySql.Data.MySqlClient" を与え、第 2 引数には MySqlMigrationSqlGenerator クラスを初期化して与えます。

MySqlMigrationSqlGenerator クラスが属する名前空間は Connector/NET 8.0 になって変わったようで MySql.Data.EntityFramework となっていますので注意してください。(v6.x の時代は MySql.Data.Entity だったはずです)

参考記事に書いてあったコードは上記と違いますが、参考記事の通りとしても問題なく Add-Migration Initial, Update-Database できることは確認できました。しかし、参考記事のコードがエラーメッセージの「追加の SQL ジェネレーターを登録」をどう解決しているのか分からなかったので、エラーメッセージ通りにコーディングしました。

(6) Update-Database

Update-Database で MySQL に必要なデータベースとテーブルを生成します。成功すると、上のステップ「(5) Add-Migration」で生成された Configuration.cs ファイルの内容に従って ASP.NET Identity 用のテーブルが生成されます。下の画像を見てください。

生成されたデータベース

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

参考記事では Update-Database で "Specified key was too long; max key length is 767 bytes" というエラーとなったそうです。なぜ参考記事でその問題が起こったのか、この記事では問題なかったかは以下のようなことだと思います。

テーブル AspNetUserRoles は UserId と RoleId がそれぞれ nvarchar(128) で��結主キーの設定になるのですが、charset が utf8 で一文字 3 バイトですと 128 x 2 x 3 = 768 となって制限の 767 バイトを超えます。それが参考記事の問題のようです。

一方、この記事では MySQL 8.x を使っているので上限が 3,072 バイトになっています。(MySQL 5.7 以降では _large_prefix が ON となっており、767 バイトの制限が 3,072 バイトに拡張されているとのこと)。文字コードは utf8mb4 なので一文字 4 バイトになり、128 x 2 x 4 = 1024 < 3072 なので問題ないということのようです。


旧来のフォーム認証の場合、ASP.NET の認証・承認システムとデータベースの間にプロバイダを配置して、プロバイダを入れ替えることによりいろいろなデータベースに対応していました。例えば SQL Server の場合は専用の SqlMembershipProvider が提供されています。

異なるデーターベースを使う場合はプロバイダを入れ替えて対応します。例えば MySQL の場合は Oracle が提供している MySQLMembershipProvider を利用できます。ただし、プロバイダが提供されていなければ自力でコードを書いてプロバイダを作成しなければなりません。

ASP.NET Identity では上に書いたように参照設定の追加、web.config の設定、追加の SQL ジェネレーター登録(これはすべてのケースで必要かは分かりませんが)で可能なようです。個人的には以前より分かりにくくなった感じがしますが・・・

Tags: ,

MVC

About this blog

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

Calendar

<<  June 2020  >>
MoTuWeThFrSaSu
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345

View posts in large calendar