ASP.NET Core での Identity モデルのカスタマイズIdentity model customization in ASP.NET Core

によってArthur VickersBy Arthur Vickers

ASP.NET Core Identity は、管理および ASP.NET Core アプリでユーザー アカウントを格納するためのフレームワークを提供します。ASP.NET Core Identity provides a framework for managing and storing user accounts in ASP.NET Core apps. Id が、プロジェクトに追加時に個々 のユーザー アカウント認証メカニズムとして選択されます。Identity is added to your project when Individual User Accounts is selected as the authentication mechanism. 既定では、Id はなりますの Entity Framework (EF) を使用して、コア データ モデル。By default, Identity makes use of an Entity Framework (EF) Core data model. この記事では、Id モデルをカスタマイズする方法について説明します。This article describes how to customize the Identity model.

Identity と EF Core のマイグレーションIdentity and EF Core Migrations

Id がどのように機能するかを把握するのに役立ちますが、モデルを調べる前に、 EF コア移行を作成してデータベースを更新します。Before examining the model, it's useful to understand how Identity works with EF Core Migrations to create and update a database. 最上位のレベルでは、手順は次のとおりです。At the top level, the process is:

  1. 定義または更新をコードでデータ モデルします。Define or update a data model in code.
  2. このモデルに変更をデータベースに適用できる変換への移行を追加します。Add a Migration to translate this model into changes that can be applied to the database.
  3. 移行が正しく、開発者の意図を表すことを確認します。Check that the Migration correctly represents your intentions.
  4. モデルと同期するデータベースの更新への移行を適用します。Apply the Migration to update the database to be in sync with the model.
  5. 手順 1. ~ 4. をさらに、モデルを調整し、データベースの同期を維持します。Repeat steps 1 through 4 to further refine the model and keep the database in sync.

追加して、移行を適用するには、次の方法のいずれかを使用します。Use one of the following approaches to add and apply Migrations:

  • パッケージ マネージャー コンソール(PMC) ウィンドウの場合、Visual Studio を使用します。The Package Manager Console (PMC) window if using Visual Studio. 詳細については、次を参照してください。 EF Core の優れた PMC ツールします。For more information, see EF Core PMC tools.
  • .NET Core CLI のコマンドラインを使用する場合。The .NET Core CLI if using the command line. 詳細については、次を参照してください。 EF Core .NET コマンド ライン ツールします。For more information, see EF Core .NET command line tools.
  • クリックすると、適用移行アプリの実行時にエラー ページ ボタンをします。Clicking the Apply Migrations button on the error page when the app is run.

ASP.NET Core では、開発時のエラー ページ ハンドラーがあります。ASP.NET Core has a development-time error page handler. ハンドラーは、アプリの実行時に、移行を適用できます。The handler can apply migrations when the app is run. 通常、実稼働アプリは、移行からの SQL スクリプトを生成し、管理されたアプリとデータベースの配置の一部としてデータベースの変更をデプロイします。Production apps typically generate SQL scripts from the migrations and deploy database changes as part of a controlled app and database deployment.

Id を使用して新しいアプリが作成されると、手順 1. と上記の 2 が完了しました既に。When a new app using Identity is created, steps 1 and 2 above have already been completed. つまり、初期のデータ モデルが既に存在して、最初の移行がプロジェクトに追加されました。That is, the initial data model already exists, and the initial migration has been added to the project. 最初の移行は、データベースに適用する必要があります。The initial migration still needs to be applied to the database. 次の方法のいずれかでは、最初の移行を適用できます。The initial migration can be applied via one of the following approaches:

  • 実行Update-DatabasePMC でします。Run Update-Database in PMC.
  • 実行dotnet ef database updateコマンド シェルでします。Run dotnet ef database update in a command shell.
  • をクリックして、移行を適用アプリの実行時にエラー ページにボタンをクリックします。Click the Apply Migrations button on the error page when the app is run.

モデルに変更が加えられるとは、上記の手順を繰り返します。Repeat the preceding steps as changes are made to the model.

Identity モデルThe Identity model

エンティティ型Entity types

Id モデルは、次のエンティティ型で構成されます。The Identity model consists of the following entity types.

エンティティ型Entity type 説明Description
User ユーザーを表します。Represents the user.
Role ロールを表します。Represents a role.
UserClaim ユーザーが所有するクレームを表します。Represents a claim that a user possesses.
UserToken ユーザーの認証トークンを表します。Represents an authentication token for a user.
UserLogin ユーザーをログインに関連付けます。Associates a user with a login.
RoleClaim ロール内のすべてのユーザーに付与されるクレームを表します。Represents a claim that's granted to all users within a role.
UserRole ユーザーとロールを関連付ける結合エンティティを指定します。A join entity that associates users and roles.

エンティティ型のリレーションシップEntity type relationships

エンティティ型次の方法で相互に関連します。The entity types are related to each other in the following ways:

  • User多く持つことができますUserClaimsします。Each User can have many UserClaims.
  • User多く持つことができますUserLoginsします。Each User can have many UserLogins.
  • User多く持つことができますUserTokensします。Each User can have many UserTokens.
  • Role関連付けられた多く持つことができますRoleClaimsします。Each Role can have many associated RoleClaims.
  • User関連付けられた多く持つことができますRoles、および各Roleさまざまな使用に関連付けることができますUsersします。Each User can have many associated Roles, and each Role can be associated with many Users. これは、データベース内の結合テーブルを必要とする多対多リレーションシップです。This is a many-to-many relationship that requires a join table in the database. 結合テーブルがによって表される、UserRoleエンティティ。The join table is represented by the UserRole entity.

既定のモデルの構成Default model configuration

多くの id が定義コンテキスト クラスから継承したDbContextを構成し、モデルを使用します。Identity defines many context classes that inherit from DbContext to configure and use the model. この構成を行うを使用して、 EF Core Code First Fluent APIで、 OnModelCreatingコンテキスト クラスのメソッド。This configuration is done using the EF Core Code First Fluent API in the OnModelCreating method of the context class. 既定の構成は次のとおりです。The default configuration is:

builder.Entity<TUser>(b =>
{
    // Primary key
    b.HasKey(u => u.Id);

    // Indexes for "normalized" username and email, to allow efficient lookups
    b.HasIndex(u => u.NormalizedUserName).HasName("UserNameIndex").IsUnique();
    b.HasIndex(u => u.NormalizedEmail).HasName("EmailIndex");

    // Maps to the AspNetUsers table
    b.ToTable("AspNetUsers");

    // A concurrency token for use with the optimistic concurrency checking
    b.Property(u => u.ConcurrencyStamp).IsConcurrencyToken();

    // Limit the size of columns to use efficient database types
    b.Property(u => u.UserName).HasMaxLength(256);
    b.Property(u => u.NormalizedUserName).HasMaxLength(256);
    b.Property(u => u.Email).HasMaxLength(256);
    b.Property(u => u.NormalizedEmail).HasMaxLength(256);

    // The relationships between User and other entity types
    // Note that these relationships are configured with no navigation properties

    // Each User can have many UserClaims
    b.HasMany<TUserClaim>().WithOne().HasForeignKey(uc => uc.UserId).IsRequired();

    // Each User can have many UserLogins
    b.HasMany<TUserLogin>().WithOne().HasForeignKey(ul => ul.UserId).IsRequired();

    // Each User can have many UserTokens
    b.HasMany<TUserToken>().WithOne().HasForeignKey(ut => ut.UserId).IsRequired();

    // Each User can have many entries in the UserRole join table
    b.HasMany<TUserRole>().WithOne().HasForeignKey(ur => ur.UserId).IsRequired();
});

builder.Entity<TUserClaim>(b =>
{
    // Primary key
    b.HasKey(uc => uc.Id);

    // Maps to the AspNetUserClaims table
    b.ToTable("AspNetUserClaims");
});

builder.Entity<TUserLogin>(b =>
{
    // Composite primary key consisting of the LoginProvider and the key to use
    // with that provider
    b.HasKey(l => new { l.LoginProvider, l.ProviderKey });

    // Limit the size of the composite key columns due to common DB restrictions
    b.Property(l => l.LoginProvider).HasMaxLength(128);
    b.Property(l => l.ProviderKey).HasMaxLength(128);

    // Maps to the AspNetUserLogins table
    b.ToTable("AspNetUserLogins");
});

builder.Entity<TUserToken>(b =>
{
    // Composite primary key consisting of the UserId, LoginProvider and Name
    b.HasKey(t => new { t.UserId, t.LoginProvider, t.Name });

    // Limit the size of the composite key columns due to common DB restrictions
    b.Property(t => t.LoginProvider).HasMaxLength(maxKeyLength);
    b.Property(t => t.Name).HasMaxLength(maxKeyLength);

    // Maps to the AspNetUserTokens table
    b.ToTable("AspNetUserTokens");
});

builder.Entity<TRole>(b =>
{
    // Primary key
    b.HasKey(r => r.Id);

    // Index for "normalized" role name to allow efficient lookups
    b.HasIndex(r => r.NormalizedName).HasName("RoleNameIndex").IsUnique();

    // Maps to the AspNetRoles table
    b.ToTable("AspNetRoles");

    // A concurrency token for use with the optimistic concurrency checking
    b.Property(r => r.ConcurrencyStamp).IsConcurrencyToken();

    // Limit the size of columns to use efficient database types
    b.Property(u => u.Name).HasMaxLength(256);
    b.Property(u => u.NormalizedName).HasMaxLength(256);

    // The relationships between Role and other entity types
    // Note that these relationships are configured with no navigation properties

    // Each Role can have many entries in the UserRole join table
    b.HasMany<TUserRole>().WithOne().HasForeignKey(ur => ur.RoleId).IsRequired();

    // Each Role can have many associated RoleClaims
    b.HasMany<TRoleClaim>().WithOne().HasForeignKey(rc => rc.RoleId).IsRequired();
});

builder.Entity<TRoleClaim>(b =>
{
    // Primary key
    b.HasKey(rc => rc.Id);

    // Maps to the AspNetRoleClaims table
    b.ToTable("AspNetRoleClaims");
});

builder.Entity<TUserRole>(b =>
{
    // Primary key
    b.HasKey(r => new { r.UserId, r.RoleId });

    // Maps to the AspNetUserRoles table
    b.ToTable("AspNetUserRoles");
});

ジェネリック型のモデルModel generic types

Identity は、既定値を定義します。共通言語ランタイム上のエンティティの種類ごとの (CLR) 型の一覧にします。Identity defines default Common Language Runtime (CLR) types for each of the entity types listed above. これらの型はすべてを先頭Identity:These types are all prefixed with Identity:

  • IdentityUser
  • IdentityRole
  • IdentityUserClaim
  • IdentityUserToken
  • IdentityUserLogin
  • IdentityRoleClaim
  • IdentityUserRole

これらの型を直接使用するのではなく アプリの種類の型の基本クラスとして使用できます。Rather than using these types directly, the types can be used as base classes for the app's own types. DbContext Id によって定義されているクラスはジェネリックでは、モデルのエンティティ型の 1 つ以上の別の CLR 型を使用できるようにします。The DbContext classes defined by Identity are generic, such that different CLR types can be used for one or more of the entity types in the model. これらのジェネリック型が許可することも、User主キー (PK) データの種類を変更します。These generic types also allow the User primary key (PK) data type to be changed.

ロールについては、サポートでの Id を使用する場合、IdentityDbContextクラスを使用する必要があります。When using Identity with support for roles, an IdentityDbContext class should be used. 例:For example:

// Uses all the built-in Identity types
// Uses `string` as the key type
public class IdentityDbContext
    : IdentityDbContext<IdentityUser, IdentityRole, string>
{
}

// Uses the built-in Identity types except with a custom User type
// Uses `string` as the key type
public class IdentityDbContext<TUser>
    : IdentityDbContext<TUser, IdentityRole, string>
        where TUser : IdentityUser
{
}

// Uses the built-in Identity types except with custom User and Role types
// The key type is defined by TKey
public class IdentityDbContext<TUser, TRole, TKey> : IdentityDbContext<
    TUser, TRole, TKey, IdentityUserClaim<TKey>, IdentityUserRole<TKey>,
    IdentityUserLogin<TKey>, IdentityRoleClaim<TKey>, IdentityUserToken<TKey>>
        where TUser : IdentityUser<TKey>
        where TRole : IdentityRole<TKey>
        where TKey : IEquatable<TKey>
{
}

// No built-in Identity types are used; all are specified by generic arguments
// The key type is defined by TKey
public abstract class IdentityDbContext<
    TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken>
    : IdentityUserContext<TUser, TKey, TUserClaim, TUserLogin, TUserToken>
         where TUser : IdentityUser<TKey>
         where TRole : IdentityRole<TKey>
         where TKey : IEquatable<TKey>
         where TUserClaim : IdentityUserClaim<TKey>
         where TUserRole : IdentityUserRole<TKey>
         where TUserLogin : IdentityUserLogin<TKey>
         where TRoleClaim : IdentityRoleClaim<TKey>
         where TUserToken : IdentityUserToken<TKey>

この場合、ロール (要求のみ) がない Id を使用することも、IdentityUserContext<TUser>クラスを使用する必要があります。It's also possible to use Identity without roles (only claims), in which case an IdentityUserContext<TUser> class should be used:

// Uses the built-in non-role Identity types except with a custom User type
// Uses `string` as the key type
public class IdentityUserContext<TUser>
    : IdentityUserContext<TUser, string>
        where TUser : IdentityUser
{
}

// Uses the built-in non-role Identity types except with a custom User type
// The key type is defined by TKey
public class IdentityUserContext<TUser, TKey> : IdentityUserContext<
    TUser, TKey, IdentityUserClaim<TKey>, IdentityUserLogin<TKey>,
    IdentityUserToken<TKey>>
        where TUser : IdentityUser<TKey>
        where TKey : IEquatable<TKey>
{
}

// No built-in Identity types are used; all are specified by generic arguments, with no roles
// The key type is defined by TKey
public abstract class IdentityUserContext<
    TUser, TKey, TUserClaim, TUserLogin, TUserToken> : DbContext
        where TUser : IdentityUser<TKey>
        where TKey : IEquatable<TKey>
        where TUserClaim : IdentityUserClaim<TKey>
        where TUserLogin : IdentityUserLogin<TKey>
        where TUserToken : IdentityUserToken<TKey>
{
}

モデルのカスタマイズCustomize the model

モデルのカスタマイズの開始点では、適切なコンテキストの型から派生します。The starting point for model customization is to derive from the appropriate context type. 参照してください、ジェネリック型をモデル化セクション。See the Model generic types section. このコンテキスト型が慣例的に呼び出されるApplicationDbContextと ASP.NET Core テンプレートによって作成されます。This context type is customarily called ApplicationDbContext and is created by the ASP.NET Core templates.

コンテキストを使用して、2 つの方法でモデルを構成します。The context is used to configure the model in two ways:

  • エンティティとジェネリック型パラメーターのキーの種類を指定します。Supplying entity and key types for the generic type parameters.
  • オーバーライドするOnModelCreatingこれらの型のマッピングを変更します。Overriding OnModelCreating to modify the mapping of these types.

オーバーライドするときにOnModelCreatingbase.OnModelCreating最初に呼び出す必要があります。 オーバーライドする側の構成を次に呼び出す必要があります。When overriding OnModelCreating, base.OnModelCreating should be called first; the overriding configuration should be called next. EF Core には、最後の 1 つの wins のポリシー構成を一般があります。EF Core generally has a last-one-wins policy for configuration. たとえば場合、ToTableエンティティ型のメソッドが 1 つのテーブルの名前の最初と呼ばれ、もう一度後で別のテーブルの名前を持つ 2 番目の呼び出し内のテーブル名が使用されます。For example, if the ToTable method for an entity type is called first with one table name and then again later with a different table name, the table name in the second call is used.

カスタム ユーザー データCustom user data

カスタム ユーザー データから継承することではサポートされてIdentityUserします。Custom user data is supported by inheriting from IdentityUser. この型名前を指定するが通例ApplicationUser:It's customary to name this type ApplicationUser:

public class ApplicationUser : IdentityUser
{
    public string CustomTag { get; set; }
}

使用して、ApplicationUserに関しては、汎用引数として型。Use the ApplicationUser type as a generic argument for the context:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
    }
}

オーバーライドする必要はありませんOnModelCreatingで、ApplicationDbContextクラス。There's no need to override OnModelCreating in the ApplicationDbContext class. EF Core のマップ、CustomTag慣例プロパティ。EF Core maps the CustomTag property by convention. データベースを新たに作成する更新が必要、CustomTag列。However, the database needs to be updated to create a new CustomTag column. 列を作成するには、移行を追加および」の説明に従って、データベースを更新Id と EF Core の移行します。To create the column, add a migration, and then update the database as described in Identity and EF Core Migrations.

Update Pages/Shared/_LoginPartial.cshtmlと置換IdentityUserApplicationUser:Update Pages/Shared/_LoginPartial.cshtml and replace IdentityUser with ApplicationUser:

@using Microsoft.AspNetCore.Identity
@using WebApp1.Areas.Identity.Data
@inject SignInManager<ApplicationUser> SignInManager
@inject UserManager<ApplicationUser> UserManager

Update Areas/Identity/IdentityHostingStartup.csまたはStartup.ConfigureServicesと置換IdentityUserApplicationUserします。Update Areas/Identity/IdentityHostingStartup.cs or Startup.ConfigureServices and replace IdentityUser with ApplicationUser.

services.AddDefaultIdentity<ApplicationUser>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultUI();

ASP.NET Core 2.1 以降では、Identity は、Razor クラス ライブラリとして提供されます。In ASP.NET Core 2.1 or later, Identity is provided as a Razor Class Library. 詳細については、「 ASP.NET Core プロジェクト内のスキャフォールディング Id 」を参照してください。For more information, see ASP.NET Core プロジェクト内のスキャフォールディング Id. したがって、上記のコードへの呼び出しが必要です。AddDefaultUIします。Consequently, the preceding code requires a call to AddDefaultUI. Id ファイルをプロジェクトに追加する Identity scaffolder を使用した場合への呼び出しを削除AddDefaultUIします。If the Identity scaffolder was used to add Identity files to the project, remove the call to AddDefaultUI. 詳細については次を参照してください:For more information, see:

主キーの型の変更Change the primary key type

データベースが作成された後に、PK 列のデータ型への変更は多くのデータベース システムで問題が発生します。A change to the PK column's data type after the database has been created is problematic on many database systems. 通常、主キーを変更するには、削除して、テーブルを再作成する必要があります。Changing the PK typically involves dropping and re-creating the table. そのため、データベースが作成されたときに、最初の移行でキーの種類を指定してください。Therefore, key types should be specified in the initial migration when the database is created.

主キーの種類を変更する次の手順に従います。Follow these steps to change the PK type:

  1. データベースが作成された場合、PK 変更する前に実行Drop-Database(PMC) またはdotnet ef database drop(.NET Core CLI) を削除します。If the database was created before the PK change, run Drop-Database (PMC) or dotnet ef database drop (.NET Core CLI) to delete it.

  2. データベースの削除を確定した後で初期の移行を削除Remove-Migration(PMC) またはdotnet ef migrations remove(.NET Core CLI)。After confirming deletion of the database, remove the initial migration with Remove-Migration (PMC) or dotnet ef migrations remove (.NET Core CLI).

  3. 更新プログラム、ApplicationDbContextクラスから派生するIdentityDbContext<TUser,TRole,TKey>します。Update the ApplicationDbContext class to derive from IdentityDbContext<TUser,TRole,TKey>. 新しいキーの種類を指定TKeyします。Specify the new key type for TKey. たとえば、使用するため、Guidキーの種類。For example, to use a Guid key type:

    public class ApplicationDbContext
        : IdentityDbContext<IdentityUser<Guid>, IdentityRole<Guid>, Guid>
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }
    }
    

    上記のコードでは、ジェネリック クラスでIdentityUser<TKey>IdentityRole<TKey>新しいキーの種類を使用するように指定する必要があります。In the preceding code, the generic classes IdentityUser<TKey> and IdentityRole<TKey> must be specified to use the new key type.

    上記のコードでは、ジェネリック クラスでIdentityUser<TKey>IdentityRole<TKey>新しいキーの種類を使用するように指定する必要があります。In the preceding code, the generic classes IdentityUser<TKey> and IdentityRole<TKey> must be specified to use the new key type.

    Startup.ConfigureServices ジェネリック ユーザーを使用する更新する必要があります。Startup.ConfigureServices must be updated to use the generic user:

    services.AddDefaultIdentity<IdentityUser<Guid>>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();
    
    services.AddIdentity<IdentityUser<Guid>, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();
    
    services.AddIdentity<IdentityUser<Guid>, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext, Guid>()
            .AddDefaultTokenProviders();
    
  4. 場合、カスタムApplicationUserクラスが使用されているから継承するクラスを更新IdentityUserします。If a custom ApplicationUser class is being used, update the class to inherit from IdentityUser. 例:For example:

    using System;
    using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
    
    public class ApplicationUser : IdentityUser<Guid>
    {
        public string CustomTag { get; set; }        
    }
    
    using System;
    using Microsoft.AspNetCore.Identity;
    
    public class ApplicationUser : IdentityUser<Guid>
    {
        public string CustomTag { get; set; }
    }
    

    UpdateApplicationDbContextカスタムを参照するApplicationUserクラス。Update ApplicationDbContext to reference the custom ApplicationUser class:

    public class ApplicationDbContext
        : IdentityDbContext<ApplicationUser, IdentityRole<Guid>, Guid>
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }
    }
    

    Id サービスを追加するときに、カスタムのデータベース コンテキスト クラスを登録Startup.ConfigureServices:Register the custom database context class when adding the Identity service in Startup.ConfigureServices:

    services.AddDefaultIdentity<ApplicationUser>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultUI()
            .AddDefaultTokenProviders();
    

    分析することで、プライマリ キーのデータ型が推論される、 DbContextオブジェクト。The primary key's data type is inferred by analyzing the DbContext object.

    ASP.NET Core 2.1 以降では、Identity は、Razor クラス ライブラリとして提供されます。In ASP.NET Core 2.1 or later, Identity is provided as a Razor Class Library. 詳細については、「 ASP.NET Core プロジェクト内のスキャフォールディング Id 」を参照してください。For more information, see ASP.NET Core プロジェクト内のスキャフォールディング Id. したがって、上記のコードへの呼び出しが必要です。AddDefaultUIします。Consequently, the preceding code requires a call to AddDefaultUI. Id ファイルをプロジェクトに追加する Identity scaffolder を使用した場合への呼び出しを削除AddDefaultUIします。If the Identity scaffolder was used to add Identity files to the project, remove the call to AddDefaultUI.

    services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();
    

    分析することで、プライマリ キーのデータ型が推論される、 DbContextオブジェクト。The primary key's data type is inferred by analyzing the DbContext object.

    services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext, Guid>()
            .AddDefaultTokenProviders();
    

    AddEntityFrameworkStoresメソッドは、TKey主キーのデータ型を表す型。The AddEntityFrameworkStores method accepts a TKey type indicating the primary key's data type.

  5. 場合、カスタムApplicationRoleクラスが使用されているから継承するクラスを更新IdentityRole<TKey>します。If a custom ApplicationRole class is being used, update the class to inherit from IdentityRole<TKey>. 例:For example:

    using System;
    using Microsoft.AspNetCore.Identity;
    
    public class ApplicationRole : IdentityRole<Guid>
    {
        public string Description { get; set; }
    }
    

    UpdateApplicationDbContextカスタムを参照するApplicationRoleクラス。Update ApplicationDbContext to reference the custom ApplicationRole class. たとえば、次のクラスは参照カスタムApplicationUserおよびカスタムApplicationRole:For example, the following class references a custom ApplicationUser and a custom ApplicationRole:

    using System;
    using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
    using Microsoft.EntityFrameworkCore;
    
    public class ApplicationDbContext :
        IdentityDbContext<ApplicationUser, ApplicationRole, Guid>
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }
    }
    

    Id サービスを追加するときに、カスタムのデータベース コンテキスト クラスを登録Startup.ConfigureServices:Register the custom database context class when adding the Identity service in Startup.ConfigureServices:

    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<CookiePolicyOptions>(options =>
        {
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });
    
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));
    
        services.AddIdentity<ApplicationUser, ApplicationRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultUI()
                .AddDefaultTokenProviders();
    
        services.AddMvc()
                .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }
    

    分析することで、プライマリ キーのデータ型が推論される、 DbContextオブジェクト。The primary key's data type is inferred by analyzing the DbContext object.

    ASP.NET Core 2.1 以降では、Identity は、Razor クラス ライブラリとして提供されます。In ASP.NET Core 2.1 or later, Identity is provided as a Razor Class Library. 詳細については、「 ASP.NET Core プロジェクト内のスキャフォールディング Id 」を参照してください。For more information, see ASP.NET Core プロジェクト内のスキャフォールディング Id. したがって、上記のコードへの呼び出しが必要です。AddDefaultUIします。Consequently, the preceding code requires a call to AddDefaultUI. Id ファイルをプロジェクトに追加する Identity scaffolder を使用した場合への呼び出しを削除AddDefaultUIします。If the Identity scaffolder was used to add Identity files to the project, remove the call to AddDefaultUI.

    using System;
    using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
    using Microsoft.EntityFrameworkCore;
    
    public class ApplicationDbContext : 
        IdentityDbContext<ApplicationUser, ApplicationRole, Guid>
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }
    }
    

    Id サービスを追加するときに、カスタムのデータベース コンテキスト クラスを登録Startup.ConfigureServices:Register the custom database context class when adding the Identity service in Startup.ConfigureServices:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));
    
        services.AddIdentity<ApplicationUser, ApplicationRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders();
    
        services.AddMvc()
            .AddRazorPagesOptions(options =>
            {
                options.Conventions.AuthorizeFolder("/Account/Manage");
                options.Conventions.AuthorizePage("/Account/Logout");
            });
    
        services.AddSingleton<IEmailSender, EmailSender>();
    }
    

    分析することで、プライマリ キーのデータ型が推論される、 DbContextオブジェクト。The primary key's data type is inferred by analyzing the DbContext object.

    using System;
    using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
    using Microsoft.EntityFrameworkCore;
    
    public class ApplicationDbContext : 
        IdentityDbContext<ApplicationUser, ApplicationRole, Guid>
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }
    }
    

    Id サービスを追加するときに、カスタムのデータベース コンテキスト クラスを登録Startup.ConfigureServices:Register the custom database context class when adding the Identity service in Startup.ConfigureServices:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ApplicationDbContext>(options => 
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));
    
        services.AddIdentity<ApplicationUser, ApplicationRole>()
                .AddEntityFrameworkStores<ApplicationDbContext, Guid>()
                .AddDefaultTokenProviders();
    
        services.AddMvc();
    
        services.AddTransient<IEmailSender, AuthMessageSender>();
        services.AddTransient<ISmsSender, AuthMessageSender>();
    }
    

    AddEntityFrameworkStoresメソッドは、TKey主キーのデータ型を表す型。The AddEntityFrameworkStores method accepts a TKey type indicating the primary key's data type.

ナビゲーション プロパティの追加Add navigation properties

リレーションシップのモデルの構成を変更すると、その他の変更よりも難しくことができます。Changing the model configuration for relationships can be more difficult than making other changes. 新しい追加のリレーションシップを作成するのではなく、既存のリレーションシップを置き換えるに注意する必要があります。Care must be taken to replace the existing relationships rather than create new, additional relationships. 具体的には、変更されたリレーションシップでは、既存のリレーションシップとして同じ外部キー (FK) プロパティを指定する必要があります。In particular, the changed relationship must specify the same foreign key (FK) property as the existing relationship. 間のリレーションシップなどUsersUserClaims、次のように、既定では。For example, the relationship between Users and UserClaims is, by default, specified as follows:

builder.Entity<TUser>(b =>
{
    // Each User can have many UserClaims
    b.HasMany<TUserClaim>()
     .WithOne()
     .HasForeignKey(uc => uc.UserId)
     .IsRequired();
});

このリレーションシップの FK として指定された、UserClaim.UserIdプロパティ。The FK for this relationship is specified as the UserClaim.UserId property. HasMany WithOneはナビゲーション プロパティのないリレーションシップを作成する引数を指定しないと呼ばれます。HasMany and WithOne are called without arguments to create the relationship without navigation properties.

ナビゲーション プロパティを追加ApplicationUserに関連付けできるUserClaimsユーザーから参照できます。Add a navigation property to ApplicationUser that allows associated UserClaims to be referenced from the user:

public class ApplicationUser : IdentityUser
{
    public virtual ICollection<IdentityUserClaim<string>> Claims { get; set; }
}

TKeyIdentityUserClaim<TKey>はユーザーの PK に指定された型です。The TKey for IdentityUserClaim<TKey> is the type specified for the PK of users. この場合、TKeystring既定値が使用されているためです。In this case, TKey is string because the defaults are being used. いないの PK 型、UserClaimエンティティ型。It's not the PK type for the UserClaim entity type.

ナビゲーション プロパティが存在するようになりましたことで構成する必要がありますOnModelCreating:Now that the navigation property exists, it must be configured in OnModelCreating:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<ApplicationUser>(b =>
        {
            // Each User can have many UserClaims
            b.HasMany(e => e.Claims)
                .WithOne()
                .HasForeignKey(uc => uc.UserId)
                .IsRequired();
        });
    }
}

呼び出しで指定されたナビゲーション プロパティでのみが、以前とまったく同じ関係が構成されていることに注意してください。HasManyします。Notice that relationship is configured exactly as it was before, only with a navigation property specified in the call to HasMany.

ナビゲーション プロパティは、データベースではなく、EF モデルにのみ存在します。The navigation properties only exist in the EF model, not the database. リレーションシップの外部キーが変更されていないため、この種のモデルの変更は更新するデータベースを必要としません。Because the FK for the relationship hasn't changed, this kind of model change doesn't require the database to be updated. これは、変更を行った後の移行を追加することで確認できます。This can be checked by adding a migration after making the change. UpDownメソッドは空です。The Up and Down methods are empty.

すべてのユーザー ナビゲーション プロパティの追加Add all User navigation properties

次の例では、ガイダンスとして、上のセクションを使用して、ユーザーのすべてのリレーションシップの一方向のナビゲーション プロパティを構成します。Using the section above as guidance, the following example configures unidirectional navigation properties for all relationships on User:

public class ApplicationUser : IdentityUser
{
    public virtual ICollection<IdentityUserClaim<string>> Claims { get; set; }
    public virtual ICollection<IdentityUserLogin<string>> Logins { get; set; }
    public virtual ICollection<IdentityUserToken<string>> Tokens { get; set; }
    public virtual ICollection<IdentityUserRole<string>> UserRoles { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<ApplicationUser>(b =>
        {
            // Each User can have many UserClaims
            b.HasMany(e => e.Claims)
                .WithOne()
                .HasForeignKey(uc => uc.UserId)
                .IsRequired();

            // Each User can have many UserLogins
            b.HasMany(e => e.Logins)
                .WithOne()
                .HasForeignKey(ul => ul.UserId)
                .IsRequired();

            // Each User can have many UserTokens
            b.HasMany(e => e.Tokens)
                .WithOne()
                .HasForeignKey(ut => ut.UserId)
                .IsRequired();

            // Each User can have many entries in the UserRole join table
            b.HasMany(e => e.UserRoles)
                .WithOne()
                .HasForeignKey(ur => ur.UserId)
                .IsRequired();
        });
    }
}

ユーザーおよびロールのナビゲーション プロパティの追加Add User and Role navigation properties

次の例では、ガイダンスとして、上のセクションを使用して、ユーザーおよびロールのすべての関係のナビゲーション プロパティを構成します。Using the section above as guidance, the following example configures navigation properties for all relationships on User and Role:

public class ApplicationUser : IdentityUser
{
    public virtual ICollection<IdentityUserClaim<string>> Claims { get; set; }
    public virtual ICollection<IdentityUserLogin<string>> Logins { get; set; }
    public virtual ICollection<IdentityUserToken<string>> Tokens { get; set; }
    public virtual ICollection<ApplicationUserRole> UserRoles { get; set; }
}

public class ApplicationRole : IdentityRole
{
    public virtual ICollection<ApplicationUserRole> UserRoles { get; set; }
}

public class ApplicationUserRole : IdentityUserRole<string>
{
    public virtual ApplicationUser User { get; set; }
    public virtual ApplicationRole Role { get; set; }
}
public class ApplicationDbContext
    : IdentityDbContext<
        ApplicationUser, ApplicationRole, string,
        IdentityUserClaim<string>, ApplicationUserRole, IdentityUserLogin<string>,
        IdentityRoleClaim<string>, IdentityUserToken<string>>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<ApplicationUser>(b =>
        {
            // Each User can have many UserClaims
            b.HasMany(e => e.Claims)
                .WithOne()
                .HasForeignKey(uc => uc.UserId)
                .IsRequired();

            // Each User can have many UserLogins
            b.HasMany(e => e.Logins)
                .WithOne()
                .HasForeignKey(ul => ul.UserId)
                .IsRequired();

            // Each User can have many UserTokens
            b.HasMany(e => e.Tokens)
                .WithOne()
                .HasForeignKey(ut => ut.UserId)
                .IsRequired();

            // Each User can have many entries in the UserRole join table
            b.HasMany(e => e.UserRoles)
                .WithOne(e => e.User)
                .HasForeignKey(ur => ur.UserId)
                .IsRequired();
        });

        modelBuilder.Entity<ApplicationRole>(b =>
        {
            // Each Role can have many entries in the UserRole join table
            b.HasMany(e => e.UserRoles)
                .WithOne(e => e.Role)
                .HasForeignKey(ur => ur.RoleId)
                .IsRequired();
        });

    }
}

メモ:Notes:

  • この例では、UserRole結合エンティティで、ユーザーからロールへの多対多リレーションシップを移動するが必要です。This example also includes the UserRole join entity, which is needed to navigate the many-to-many relationship from Users to Roles.
  • 反映するようにナビゲーション プロパティの型を変更してApplicationXxx型は、の代わりに使用されているようになりましたIdentityXxx型。Remember to change the types of the navigation properties to reflect that ApplicationXxx types are now being used instead of IdentityXxx types.
  • 使用してください、ApplicationXxxジェネリックApplicationContext定義します。Remember to use the ApplicationXxx in the generic ApplicationContext definition.

すべてのナビゲーション プロパティの追加Add all navigation properties

次の例では、ガイダンスとして、上のセクションを使用して、すべてのエンティティ型ですべての関係のナビゲーション プロパティを構成します。Using the section above as guidance, the following example configures navigation properties for all relationships on all entity types:

public class ApplicationUser : IdentityUser
{
    public virtual ICollection<ApplicationUserClaim> Claims { get; set; }
    public virtual ICollection<ApplicationUserLogin> Logins { get; set; }
    public virtual ICollection<ApplicationUserToken> Tokens { get; set; }
    public virtual ICollection<ApplicationUserRole> UserRoles { get; set; }
}

public class ApplicationRole : IdentityRole
{
    public virtual ICollection<ApplicationUserRole> UserRoles { get; set; }
    public virtual ICollection<ApplicationRoleClaim> RoleClaims { get; set; }
}

public class ApplicationUserRole : IdentityUserRole<string>
{
    public virtual ApplicationUser User { get; set; }
    public virtual ApplicationRole Role { get; set; }
}

public class ApplicationUserClaim : IdentityUserClaim<string>
{
    public virtual ApplicationUser User { get; set; }
}

public class ApplicationUserLogin : IdentityUserLogin<string>
{
    public virtual ApplicationUser User { get; set; }
}

public class ApplicationRoleClaim : IdentityRoleClaim<string>
{
    public virtual ApplicationRole Role { get; set; }
}

public class ApplicationUserToken : IdentityUserToken<string>
{
    public virtual ApplicationUser User { get; set; }
}
public class ApplicationDbContext
    : IdentityDbContext<
        ApplicationUser, ApplicationRole, string,
        ApplicationUserClaim, ApplicationUserRole, ApplicationUserLogin,
        ApplicationRoleClaim, ApplicationUserToken>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<ApplicationUser>(b =>
        {
            // Each User can have many UserClaims
            b.HasMany(e => e.Claims)
                .WithOne(e => e.User)
                .HasForeignKey(uc => uc.UserId)
                .IsRequired();

            // Each User can have many UserLogins
            b.HasMany(e => e.Logins)
                .WithOne(e => e.User)
                .HasForeignKey(ul => ul.UserId)
                .IsRequired();

            // Each User can have many UserTokens
            b.HasMany(e => e.Tokens)
                .WithOne(e => e.User)
                .HasForeignKey(ut => ut.UserId)
                .IsRequired();

            // Each User can have many entries in the UserRole join table
            b.HasMany(e => e.UserRoles)
                .WithOne(e => e.User)
                .HasForeignKey(ur => ur.UserId)
                .IsRequired();
        });

        modelBuilder.Entity<ApplicationRole>(b =>
        {
            // Each Role can have many entries in the UserRole join table
            b.HasMany(e => e.UserRoles)
                .WithOne(e => e.Role)
                .HasForeignKey(ur => ur.RoleId)
                .IsRequired();

            // Each Role can have many associated RoleClaims
            b.HasMany(e => e.RoleClaims)
                .WithOne(e => e.Role)
                .HasForeignKey(rc => rc.RoleId)
                .IsRequired();
        });
    }
}

複合キーの使用Use composite keys

前のセクションでは、Id モデルで使用されるキーの型の変更が示されています。The preceding sections demonstrated changing the type of key used in the Identity model. 複合キーを使用するキーの Id モデルを変更すると、サポートされていないかお勧めします。Changing the Identity key model to use composite keys isn't supported or recommended. Id を持つ複合キーを使用するには、Identity manager のコードが、モデルと対話する方法を変更する必要があります。Using a composite key with Identity involves changing how the Identity manager code interacts with the model. このカスタマイズでは、このドキュメントの範囲外です。This customization is beyond the scope of this document.

テーブル名/列名とファセットの変更Change table/column names and facets

テーブルと列の名前を変更するには、呼び出すbase.OnModelCreatingします。To change the names of tables and columns, call base.OnModelCreating. 次に、既定値のいずれかを上書きする構成を追加します。Then, add configuration to override any of the defaults. たとえば、Identity のすべてのテーブルの名前を変更します。For example, to change the name of all the Identity tables:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.Entity<IdentityUser>(b =>
    {
        b.ToTable("MyUsers");
    });

    modelBuilder.Entity<IdentityUserClaim<string>>(b =>
    {
        b.ToTable("MyUserClaims");
    });

    modelBuilder.Entity<IdentityUserLogin<string>>(b =>
    {
        b.ToTable("MyUserLogins");
    });

    modelBuilder.Entity<IdentityUserToken<string>>(b =>
    {
        b.ToTable("MyUserTokens");
    });

    modelBuilder.Entity<IdentityRole>(b =>
    {
        b.ToTable("MyRoles");
    });

    modelBuilder.Entity<IdentityRoleClaim<string>>(b =>
    {
        b.ToTable("MyRoleClaims");
    });

    modelBuilder.Entity<IdentityUserRole<string>>(b =>
    {
        b.ToTable("MyUserRoles");
    });
}

これらの例では、既定の Id 型を使用します。These examples use the default Identity types. などのアプリの種類を使用して場合ApplicationUser、既定値の型ではなく、その型を構成します。If using an app type such as ApplicationUser, configure that type instead of the default type.

次の例では、一部の列名を変更します。The following example changes some column names:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.Entity<IdentityUser>(b =>
    {
        b.Property(e => e.Email).HasColumnName("EMail");
    });

    modelBuilder.Entity<IdentityUserClaim<string>>(b =>
    {
        b.Property(e => e.ClaimType).HasColumnName("CType");
        b.Property(e => e.ClaimValue).HasColumnName("CValue");
    });
}

特定のデータベース列のいくつかの種類を構成することができますファセット(たとえば、最大string許容長)。Some types of database columns can be configured with certain facets (for example, the maximum string length allowed). 次の例では、いくつかの列の最大長を設定するstringモデル内のプロパティ。The following example sets column maximum lengths for several string properties in the model:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.Entity<IdentityUser>(b =>
    {
        b.Property(u => u.UserName).HasMaxLength(128);
        b.Property(u => u.NormalizedUserName).HasMaxLength(128);
        b.Property(u => u.Email).HasMaxLength(128);
        b.Property(u => u.NormalizedEmail).HasMaxLength(128);
    });

    modelBuilder.Entity<IdentityUserToken<string>>(b =>
    {
        b.Property(t => t.LoginProvider).HasMaxLength(128);
        b.Property(t => t.Name).HasMaxLength(128);
    });
}

別のスキーマへのマップMap to a different schema

スキーマは、データベース プロバイダーにわたる動作が異なることができます。Schemas can behave differently across database providers. 既定値は、SQL Server のすべてのテーブルを作成する、 dboスキーマ。For SQL Server, the default is to create all tables in the dbo schema. 別のスキーマ内のテーブルを作成できます。The tables can be created in a different schema. 例えば:For example:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.HasDefaultSchema("notdbo");
}

遅延読み込みLazy loading

このセクションでは、Id モデルで遅延読み込みプロキシのサポートが追加されます。In this section, support for lazy-loading proxies in the Identity model is added. ナビゲーション プロパティが読み込まれている確認せずに使用することができるので、遅延読み込みの使用をお勧めします。Lazy-loading is useful since it allows navigation properties to be used without first ensuring they're loaded.

エンティティの種類にできるに適したいくつかの方法で遅延読み込み」の説明に従って、 EF Core ドキュメントします。Entity types can be made suitable for lazy-loading in several ways, as described in the EF Core documentation. わかりやすくするために、必要があります、遅延読み込みプロキシを使用します。For simplicity, use lazy-loading proxies, which requires:

次の例では、通話UseLazyLoadingProxiesStartup.ConfigureServices:The following example demonstrates calling UseLazyLoadingProxies in Startup.ConfigureServices:

services
    .AddDbContext<ApplicationDbContext>(
        b => b.UseSqlServer(connectionString)
              .UseLazyLoadingProxies())
    .AddDefaultIdentity<ApplicationUser>()
    .AddEntityFrameworkStores<ApplicationDbContext>();

エンティティ型にナビゲーション プロパティを追加する方法のガイダンスについては、前の例を参照してください。Refer to the preceding examples for guidance on adding navigation properties to the entity types.

その他の技術情報Additional resources