// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Linq; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore.Identity.EntityFrameworkCore { /// /// Base class for the Entity Framework database context used for identity. /// /// The type of the user objects. public class IdentityUserContext : IdentityUserContext where TUser : IdentityUser { /// /// Initializes a new instance of . /// /// The options to be used by a . public IdentityUserContext(DbContextOptions options) : base(options) { } /// /// Initializes a new instance of the class. /// protected IdentityUserContext() { } } /// /// Base class for the Entity Framework database context used for identity. /// /// The type of user objects. /// The type of the primary key for users and roles. public class IdentityUserContext : IdentityUserContext, IdentityUserLogin, IdentityUserToken> where TUser : IdentityUser where TKey : IEquatable { /// /// Initializes a new instance of the db context. /// /// The options to be used by a . public IdentityUserContext(DbContextOptions options) : base(options) { } /// /// Initializes a new instance of the class. /// protected IdentityUserContext() { } } /// /// Base class for the Entity Framework database context used for identity. /// /// The type of user objects. /// The type of the primary key for users and roles. /// The type of the user claim object. /// The type of the user login object. /// The type of the user token object. public abstract class IdentityUserContext : DbContext where TUser : IdentityUser where TKey : IEquatable where TUserClaim : IdentityUserClaim where TUserLogin : IdentityUserLogin where TUserToken : IdentityUserToken { /// /// Initializes a new instance of the class. /// /// The options to be used by a . public IdentityUserContext(DbContextOptions options) : base(options) { } /// /// Initializes a new instance of the class. /// protected IdentityUserContext() { } /// /// Gets or sets the of Users. /// public DbSet Users { get; set; } /// /// Gets or sets the of User claims. /// public DbSet UserClaims { get; set; } /// /// Gets or sets the of User logins. /// public DbSet UserLogins { get; set; } /// /// Gets or sets the of User tokens. /// public DbSet UserTokens { get; set; } private int GetMaxLengthForKeys() { // Need to get the actual application service provider, fallback will cause // options to not work since IEnumerable don't flow across providers var options = this.GetService() .Extensions.OfType() .FirstOrDefault()?.ApplicationServiceProvider ?.GetService>() ?.Value?.Stores; return options != null ? options.MaxLengthForKeys : 0; } /// /// Configures the schema needed for the identity framework. /// /// /// The builder being used to construct the model for this context. /// protected override void OnModelCreating(ModelBuilder builder) { var maxKeyLength = GetMaxLengthForKeys(); builder.Entity(b => { b.HasKey(u => u.Id); b.HasIndex(u => u.NormalizedUserName).HasName("UserNameIndex").IsUnique(); b.HasIndex(u => u.NormalizedEmail).HasName("EmailIndex"); b.ToTable("AspNetUsers"); b.Property(u => u.ConcurrencyStamp).IsConcurrencyToken(); 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); b.HasMany().WithOne().HasForeignKey(uc => uc.UserId).IsRequired(); b.HasMany().WithOne().HasForeignKey(ul => ul.UserId).IsRequired(); b.HasMany().WithOne().HasForeignKey(ut => ut.UserId).IsRequired(); }); builder.Entity(b => { b.HasKey(uc => uc.Id); b.ToTable("AspNetUserClaims"); }); builder.Entity(b => { b.HasKey(l => new { l.LoginProvider, l.ProviderKey }); if (maxKeyLength > 0) { b.Property(l => l.LoginProvider).HasMaxLength(maxKeyLength); b.Property(l => l.ProviderKey).HasMaxLength(maxKeyLength); } b.ToTable("AspNetUserLogins"); }); builder.Entity(b => { b.HasKey(t => new { t.UserId, t.LoginProvider, t.Name }); if (maxKeyLength > 0) { b.Property(t => t.LoginProvider).HasMaxLength(maxKeyLength); b.Property(t => t.Name).HasMaxLength(maxKeyLength); } b.ToTable("AspNetUserTokens"); }); } } }