--- title: Identity model customization in ASP.NET Core author: ajcvickers description: This article describes how to customize the underlying Entity Framework Core data model for ASP.NET Core Identity. ms.author: avickers ms.date: 10/29/2024 uid: security/authentication/customize_identity_model --- # Identity model customization in ASP.NET Core By [Arthur Vickers](https://github.com/ajcvickers) ASP.NET Core Identity provides a framework for managing and storing user accounts in ASP.NET Core apps. Identity is added to your project when **Individual User Accounts** is selected as the authentication mechanism. By default, Identity makes use of an Entity Framework (EF) Core data model. This article describes how to customize the Identity model. ## Identity and EF Core Migrations Before examining the model, it's useful to understand how Identity works with [EF Core Migrations](/ef/core/managing-schemas/migrations/) to create and update a database. At the top level, the process is: 1. Define or update a [data model in code](/ef/core/modeling/). 1. Add a Migration to translate this model into changes that can be applied to the database. 1. Check that the Migration correctly represents your intentions. 1. Apply the Migration to update the database to be in sync with the model. 1. 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: * The **Package Manager Console** (PMC) window if using Visual Studio. For more information, see [EF Core PMC tools](/ef/core/miscellaneous/cli/powershell). * The .NET CLI if using the command line. For more information, see [EF Core .NET command line tools](/ef/core/miscellaneous/cli/dotnet). * Clicking the **Apply Migrations** button on the error page when the app is run. ASP.NET Core has a development-time error page handler. The handler can apply migrations when the app is run. Production apps typically generate SQL scripts from the migrations and deploy database changes as part of a controlled app and database deployment. 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: * Run `Update-Database` in PMC. * 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. ## The Identity model ### Entity types 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](#entity-types) are related to each other in the following ways: * Each `User` can have many `UserClaims`. * Each `User` can have many `UserLogins`. * Each `User` can have many `UserTokens`. * Each `Role` can have many associated `RoleClaims`. * 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. The join table is represented by the `UserRole` entity. ### Default model configuration Identity defines many *context classes* that inherit from to configure and use the model. This configuration is done using the [EF Core Code First Fluent API](/ef/core/modeling/) in the method of the context class. The default configuration is: ```csharp builder.Entity(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().WithOne().HasForeignKey(uc => uc.UserId).IsRequired(); // Each User can have many UserLogins b.HasMany().WithOne().HasForeignKey(ul => ul.UserId).IsRequired(); // Each User can have many UserTokens b.HasMany().WithOne().HasForeignKey(ut => ut.UserId).IsRequired(); // Each User can have many entries in the UserRole join table b.HasMany().WithOne().HasForeignKey(ur => ur.UserId).IsRequired(); }); builder.Entity(b => { // Primary key b.HasKey(uc => uc.Id); // Maps to the AspNetUserClaims table b.ToTable("AspNetUserClaims"); }); builder.Entity(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(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(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().WithOne().HasForeignKey(ur => ur.RoleId).IsRequired(); // Each Role can have many associated RoleClaims b.HasMany().WithOne().HasForeignKey(rc => rc.RoleId).IsRequired(); }); builder.Entity(b => { // Primary key b.HasKey(rc => rc.Id); // Maps to the AspNetRoleClaims table b.ToTable("AspNetRoleClaims"); }); builder.Entity(b => { // Primary key b.HasKey(r => new { r.UserId, r.RoleId }); // Maps to the AspNetUserRoles table b.ToTable("AspNetUserRoles"); }); ``` ### Model generic types Identity defines default [Common Language Runtime](/dotnet/standard/glossary#clr) (CLR) types for each of the entity types listed above. 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. 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. These generic types also allow the `User` primary key (PK) data type to be changed. When using Identity with support for roles, an class should be used. For example: ```csharp // Uses all the built-in Identity types // Uses `string` as the key type public class IdentityDbContext : IdentityDbContext { } // Uses the built-in Identity types except with a custom User type // Uses `string` as the key type public class IdentityDbContext : IdentityDbContext 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 : IdentityDbContext< TUser, TRole, TKey, IdentityUserClaim, IdentityUserRole, IdentityUserLogin, IdentityRoleClaim, IdentityUserToken> where TUser : IdentityUser where TRole : IdentityRole where TKey : IEquatable { } // 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 where TUser : IdentityUser where TRole : IdentityRole where TKey : IEquatable where TUserClaim : IdentityUserClaim where TUserRole : IdentityUserRole where TUserLogin : IdentityUserLogin where TRoleClaim : IdentityRoleClaim where TUserToken : IdentityUserToken ``` It's also possible to use Identity without roles (only claims), in which case an class should be used: ```csharp // Uses the built-in non-role Identity types except with a custom User type // Uses `string` as the key type public class IdentityUserContext : IdentityUserContext 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 : IdentityUserContext< TUser, TKey, IdentityUserClaim, IdentityUserLogin, IdentityUserToken> where TUser : IdentityUser where TKey : IEquatable { } // 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 where TKey : IEquatable where TUserClaim : IdentityUserClaim where TUserLogin : IdentityUserLogin where TUserToken : IdentityUserToken { } ``` ## Customize the model The starting point for model customization is to derive from the appropriate context type. See the [Model generic types](#model-generic-types) section. This context type is customarily called `ApplicationDbContext` and is created by the ASP.NET Core templates. The context is used to configure the model in two ways: * Supplying entity and key types for the generic type parameters. * Overriding `OnModelCreating` to modify the mapping of these types. When overriding `OnModelCreating`, `base.OnModelCreating` should be called first; the overriding configuration should be called next. EF Core generally has a last-one-wins policy for configuration. 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. ***NOTE***: If the `DbContext` doesn't derive from `IdentityDbContext`, `AddEntityFrameworkStores` may not infer the correct POCO types for `TUserClaim`, `TUserLogin`, and `TUserToken`. If `AddEntityFrameworkStores` doesn't infer the correct POCO types, a workaround is to directly add the correct types via `services.AddScoped` and `UserStore<...>>`. ### Custom user data [Custom user data](xref:security/authentication/add-user-data) is supported by inheriting from `IdentityUser`. It's customary to name this type `ApplicationUser`: ```csharp public class ApplicationUser : IdentityUser { public string CustomTag { get; set; } } ``` Use the `ApplicationUser` type as a generic argument for the context: ```csharp public class ApplicationDbContext : IdentityDbContext { public ApplicationDbContext(DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); } } ``` There's no need to override `OnModelCreating` in the `ApplicationDbContext` class. EF Core maps the `CustomTag` property by convention. However, the database needs to be updated to create a new `CustomTag` column. To create the column, add a migration, and then update the database as described in [Identity and EF Core Migrations](#identity-and-ef-core-migrations). Update `Pages/Shared/_LoginPartial.cshtml` and replace `IdentityUser` with `ApplicationUser`: ```cshtml @using Microsoft.AspNetCore.Identity @using WebApp1.Areas.Identity.Data @inject SignInManager SignInManager @inject UserManager UserManager ``` Update `Areas/Identity/IdentityHostingStartup.cs` or `Startup.ConfigureServices` and replace `IdentityUser` with `ApplicationUser`. ```csharp services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores(); ``` Calling is equivalent to the following code: ```csharp services.AddAuthentication(o => { o.DefaultScheme = IdentityConstants.ApplicationScheme; o.DefaultSignInScheme = IdentityConstants.ExternalScheme; }) .AddIdentityCookies(o => { }); services.AddIdentityCore(o => { o.Stores.MaxLengthForKeys = 128; o.SignIn.RequireConfirmedAccount = true; }) .AddDefaultUI() .AddDefaultTokenProviders(); ``` Identity is provided as a Razor class library. For more information, see . Consequently, the preceding code requires a call to . If the Identity scaffolder was used to add Identity files to the project, remove the call to `AddDefaultUI`. For more information, see: * [Scaffold Identity](xref:security/authentication/scaffold-identity) * [Add, download, and delete custom user data to Identity](xref:security/authentication/add-user-data) ### Change the primary key type 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. If the database was created before the PK change, run `Drop-Database` (PMC) or `dotnet ef database drop` (.NET CLI) to delete it. 2. After confirming deletion of the database, remove the initial migration with `Remove-Migration` (PMC) or `dotnet ef migrations remove` (.NET CLI). 3. Update the `ApplicationDbContext` class to derive from . Specify the new key type for `TKey`. For example, to use a `Guid` key type: ```csharp public class ApplicationDbContext : IdentityDbContext, IdentityRole, Guid> { public ApplicationDbContext(DbContextOptions options) : base(options) { } } ``` In the preceding code, the generic classes and must be specified to use the new key type. `Startup.ConfigureServices` must be updated to use the generic user: ```csharp services.AddDefaultIdentity>(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores(); ``` 4. If a custom `ApplicationUser` class is being used, update the class to inherit from `IdentityUser`. For example: [!code-csharp[](customize-identity-model/samples/2.1/RazorPagesSampleApp/Data/ApplicationUser.cs?name=snippet_ApplicationUser&highlight=4)] Update `ApplicationDbContext` to reference the custom `ApplicationUser` class: ```csharp public class ApplicationDbContext : IdentityDbContext, Guid> { public ApplicationDbContext(DbContextOptions options) : base(options) { } } ``` Register the custom database context class when adding the Identity service in `Startup.ConfigureServices`: ```csharp services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores(); ``` The primary key's data type is inferred by analyzing the object. Identity is provided as a Razor class library. For more information, see . Consequently, the preceding code requires a call to . If the Identity scaffolder was used to add Identity files to the project, remove the call to `AddDefaultUI`. 5. If a custom `ApplicationRole` class is being used, update the class to inherit from `IdentityRole`. For example: [!code-csharp[](customize-identity-model/samples/2.1/RazorPagesSampleApp/Data/ApplicationRole.cs?name=snippet_ApplicationRole&highlight=4)] Update `ApplicationDbContext` to reference the custom `ApplicationRole` class. For example, the following class references a custom `ApplicationUser` and a custom `ApplicationRole`: [!code-csharp[](customize-identity-model/samples/2.1/RazorPagesSampleApp/Data/ApplicationDbContext.cs?name=snippet_ApplicationDbContext&highlight=5-6)] Register the custom database context class when adding the Identity service in `Startup.ConfigureServices`: [!code-csharp[](customize-identity-model/samples/2.1/RazorPagesSampleApp/Startup.cs?name=snippet_ConfigureServices&highlight=13-16)] The primary key's data type is inferred by analyzing the object. Identity is provided as a Razor class library. For more information, see . Consequently, the preceding code requires a call to . If the Identity scaffolder was used to add Identity files to the project, remove the call to `AddDefaultUI`. ### 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. In particular, the changed relationship must specify the same foreign key (FK) property as the existing relationship. For example, the relationship between `Users` and `UserClaims` is, by default, specified as follows: ```csharp builder.Entity(b => { // Each User can have many UserClaims b.HasMany() .WithOne() .HasForeignKey(uc => uc.UserId) .IsRequired(); }); ``` The FK for this relationship is specified as the `UserClaim.UserId` property. `HasMany` and `WithOne` are called without arguments to create the relationship without navigation properties. Add a navigation property to `ApplicationUser` that allows associated `UserClaims` to be referenced from the user: ```csharp public class ApplicationUser : IdentityUser { public virtual ICollection> Claims { get; set; } } ``` The `TKey` for `IdentityUserClaim` is the type specified for the PK of users. In this case, `TKey` is `string` because the defaults are being used. It's **not** the PK type for the `UserClaim` entity type. Now that the navigation property exists, it must be configured in `OnModelCreating`: ```csharp public class ApplicationDbContext : IdentityDbContext { public ApplicationDbContext(DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity(b => { // Each User can have many UserClaims b.HasMany(e => e.Claims) .WithOne() .HasForeignKey(uc => uc.UserId) .IsRequired(); }); } } ``` Notice that relationship is configured exactly as it was before, only with a navigation property specified in the call to `HasMany`. 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. 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: ```csharp public class ApplicationUser : IdentityUser { public virtual ICollection> Claims { get; set; } public virtual ICollection> Logins { get; set; } public virtual ICollection> Tokens { get; set; } public virtual ICollection> UserRoles { get; set; } } ``` ```csharp public class ApplicationDbContext : IdentityDbContext { public ApplicationDbContext(DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity(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: ```csharp public class ApplicationUser : IdentityUser { public virtual ICollection> Claims { get; set; } public virtual ICollection> Logins { get; set; } public virtual ICollection> Tokens { get; set; } public virtual ICollection UserRoles { get; set; } } public class ApplicationRole : IdentityRole { public virtual ICollection UserRoles { get; set; } } public class ApplicationUserRole : IdentityUserRole { public virtual ApplicationUser User { get; set; } public virtual ApplicationRole Role { get; set; } } ``` ```csharp public class ApplicationDbContext : IdentityDbContext< ApplicationUser, ApplicationRole, string, IdentityUserClaim, ApplicationUserRole, IdentityUserLogin, IdentityRoleClaim, IdentityUserToken> { public ApplicationDbContext(DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity(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(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: * This example also includes the `UserRole` join entity, which is needed to navigate the many-to-many relationship from Users to Roles. * Remember to change the types of the navigation properties to reflect that `Application{...}` types are now being used instead of `Identity{...}` types. * Remember to use the `Application{...}` 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: ```csharp public class ApplicationUser : IdentityUser { public virtual ICollection Claims { get; set; } public virtual ICollection Logins { get; set; } public virtual ICollection Tokens { get; set; } public virtual ICollection UserRoles { get; set; } } public class ApplicationRole : IdentityRole { public virtual ICollection UserRoles { get; set; } public virtual ICollection RoleClaims { get; set; } } public class ApplicationUserRole : IdentityUserRole { public virtual ApplicationUser User { get; set; } public virtual ApplicationRole Role { get; set; } } public class ApplicationUserClaim : IdentityUserClaim { public virtual ApplicationUser User { get; set; } } public class ApplicationUserLogin : IdentityUserLogin { public virtual ApplicationUser User { get; set; } } public class ApplicationRoleClaim : IdentityRoleClaim { public virtual ApplicationRole Role { get; set; } } public class ApplicationUserToken : IdentityUserToken { public virtual ApplicationUser User { get; set; } } ``` ```csharp public class ApplicationDbContext : IdentityDbContext< ApplicationUser, ApplicationRole, string, ApplicationUserClaim, ApplicationUserRole, ApplicationUserLogin, ApplicationRoleClaim, ApplicationUserToken> { public ApplicationDbContext(DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity(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(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 The preceding sections demonstrated changing the type of key used in the Identity model. Changing the Identity key model to use composite keys isn't supported or recommended. 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 To change the names of tables and columns, call `base.OnModelCreating`. Then, add configuration to override any of the defaults. For example, to change the name of all the Identity tables: ```csharp protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity(b => { b.ToTable("MyUsers"); }); modelBuilder.Entity>(b => { b.ToTable("MyUserClaims"); }); modelBuilder.Entity>(b => { b.ToTable("MyUserLogins"); }); modelBuilder.Entity>(b => { b.ToTable("MyUserTokens"); }); modelBuilder.Entity(b => { b.ToTable("MyRoles"); }); modelBuilder.Entity>(b => { b.ToTable("MyRoleClaims"); }); modelBuilder.Entity>(b => { b.ToTable("MyUserRoles"); }); } ``` These examples use the default Identity types. If using an app type such as `ApplicationUser`, configure that type instead of the default type. The following example changes some column names: ```csharp protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity(b => { b.Property(e => e.Email).HasColumnName("EMail"); }); modelBuilder.Entity>(b => { b.Property(e => e.ClaimType).HasColumnName("CType"); b.Property(e => e.ClaimValue).HasColumnName("CValue"); }); } ``` Some types of database columns can be configured with certain *facets* (for example, the maximum `string` length allowed). The following example sets column maximum lengths for several `string` properties in the model: ```csharp protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity(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>(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. 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: ```csharp protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.HasDefaultSchema("notdbo"); } ``` ### Lazy loading 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. Entity types can be made suitable for lazy-loading in several ways, as described in the [EF Core documentation](/ef/core/querying/related-data#lazy-loading). For simplicity, use lazy-loading proxies, which requires: * Installation of the [Microsoft.EntityFrameworkCore.Proxies](https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.Proxies/) package. * A call to inside . * Public entity types with `public virtual` navigation properties. The following example demonstrates calling `UseLazyLoadingProxies` in `Startup.ConfigureServices`: ```csharp services .AddDbContext( b => b.UseSqlServer(connectionString) .UseLazyLoadingProxies()) .AddDefaultIdentity() .AddEntityFrameworkStores(); ``` Refer to the preceding examples for guidance on adding navigation properties to the entity types. [!INCLUDE [managed-identities](~/includes/managed-identities-conn-strings.md)] ## Additional resources *