ASP.NET身份DbContext混淆

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ASP.NET身份DbContext混淆相关的知识,希望对你有一定的参考价值。

默认的MVC 5 App附带了IdentityModels.cs中的这段代码 - 这段代码用于默认模板的所有ASP.NET Identity操作:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>

    public ApplicationDbContext()
        : base("DefaultConnection")
    
    

如果我使用带有Entity Framework的视图构建一个新控制器并在对话框中创建一个“新数据上下文...”,我会为我生成这个:

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;

namespace WebApplication1.Models

    public class AllTheOtherStuffDbContext : DbContext
    
        // You can add custom code to this file. Changes will not be overwritten.
        // 
        // If you want Entity Framework to drop and regenerate your database
        // automatically whenever you change your model schema, please use data migrations.
        // For more information refer to the documentation:
        // http://msdn.microsoft.com/en-us/data/jj591621.aspx

        public AllTheOtherStuffDbContext() : base("name=AllTheOtherStuffDbContext")
        
        

        public System.Data.Entity.DbSet<WebApplication1.Models.Movie> Movies  get; set; 

    
 

如果我使用EF构建另一个控制器+视图,例如对于一个Animal模型,这个新行将在public System.Data.Entity.DbSet<WebApplication1.Models.Movie> Movies get; set; 下自动生成 - 如下所示:

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;

namespace WebApplication1.Models

    public class AllTheOtherStuffDbContext : DbContext
    
        // You can add custom code to this file. Changes will not be overwritten.
        // 
        // If you want Entity Framework to drop and regenerate your database
        // automatically whenever you change your model schema, please use data migrations.
        // For more information refer to the documentation:
        // http://msdn.microsoft.com/en-us/data/jj591621.aspx

        public AllTheOtherStuffDbContext() : base("name=AllTheOtherStuffDbContext")
        
        

        public System.Data.Entity.DbSet<WebApplication1.Models.Movie> Movies  get; set; 
        public System.Data.Entity.DbSet<WebApplication1.Models.Animal> Animals  get; set; 

    
 

ApplicationDbContext(对于所有ASP.NET标识的东西)继承自IdentityDbContextDbContext继承自AllOtherStuffDbContextDbContext(我自己的东西)继承自ApplicationDbContext

所以我的问题是:

我应该为所有其他自己的模型使用这两个中的哪一个(AllOtherStuffDbContextApplicationDbContext)?或者我应该使用默认的自动生成的DbContext,因为它不应该是使用它的问题,因为它派生自基类DbContext,还是会有一些开销?你应该在你的应用程序中只为你的所有模型使用一个ApplicationDbContext对象(我已经在某处读过)所以我甚至不应该考虑在一个应用程序中同时使用AllOtherStuffDbContextWhy is Asp.Net Identity IdentityDbContext a Black-Box??或者使用ASP.NET身份的MVC 5中的最佳实践是什么?

答案

我会使用一个继承自IdentityDbContext的Context类。通过这种方式,您可以让上下文了解您的类与IdentityUser和IdentityDbContext的角色之间的任何关系。 IdentityDbContext中的开销非常小,它基本上是一个带有两个DbSet的常规DbContext。一个用户,一个用于角色。

另一答案

IdentityDbContext有很多混淆,在Stackoverflow中快速搜索,你会发现这些问题: “How can I change the table names when using Visual Studio 2013 AspNet Identity? Merge MyDbContext with IdentityDbContext IdentityDbContext source

要回答所有这些问题,我们需要了解IdentityDbContext只是一个继承自DbContext的类。 我们来看看/// <summary> /// Base class for the Entity Framework database context used for identity. /// </summary> /// <typeparam name="TUser">The type of user objects.</typeparam> /// <typeparam name="TRole">The type of role objects.</typeparam> /// <typeparam name="TKey">The type of the primary key for users and roles.</typeparam> /// <typeparam name="TUserClaim">The type of the user claim object.</typeparam> /// <typeparam name="TUserRole">The type of the user role object.</typeparam> /// <typeparam name="TUserLogin">The type of the user login object.</typeparam> /// <typeparam name="TRoleClaim">The type of the role claim object.</typeparam> /// <typeparam name="TUserToken">The type of the user token object.</typeparam> public abstract class IdentityDbContext<TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken> : DbContext where TUser : IdentityUser<TKey, TUserClaim, TUserRole, TUserLogin> where TRole : IdentityRole<TKey, TUserRole, TRoleClaim> where TKey : IEquatable<TKey> where TUserClaim : IdentityUserClaim<TKey> where TUserRole : IdentityUserRole<TKey> where TUserLogin : IdentityUserLogin<TKey> where TRoleClaim : IdentityRoleClaim<TKey> where TUserToken : IdentityUserToken<TKey> /// <summary> /// Initializes a new instance of <see cref="IdentityDbContext"/>. /// </summary> /// <param name="options">The options to be used by a <see cref="DbContext"/>.</param> public IdentityDbContext(DbContextOptions options) : base(options) /// <summary> /// Initializes a new instance of the <see cref="IdentityDbContext" /> class. /// </summary> protected IdentityDbContext() /// <summary> /// Gets or sets the <see cref="DbSetTEntity"/> of Users. /// </summary> public DbSet<TUser> Users get; set; /// <summary> /// Gets or sets the <see cref="DbSetTEntity"/> of User claims. /// </summary> public DbSet<TUserClaim> UserClaims get; set; /// <summary> /// Gets or sets the <see cref="DbSetTEntity"/> of User logins. /// </summary> public DbSet<TUserLogin> UserLogins get; set; /// <summary> /// Gets or sets the <see cref="DbSetTEntity"/> of User roles. /// </summary> public DbSet<TUserRole> UserRoles get; set; /// <summary> /// Gets or sets the <see cref="DbSetTEntity"/> of User tokens. /// </summary> public DbSet<TUserToken> UserTokens get; set; /// <summary> /// Gets or sets the <see cref="DbSetTEntity"/> of roles. /// </summary> public DbSet<TRole> Roles get; set; /// <summary> /// Gets or sets the <see cref="DbSetTEntity"/> of role claims. /// </summary> public DbSet<TRoleClaim> RoleClaims get; set; /// <summary> /// Configures the schema needed for the identity framework. /// </summary> /// <param name="builder"> /// The builder being used to construct the model for this context. /// </param> protected override void OnModelCreating(ModelBuilder builder) builder.Entity<TUser>(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(u => u.Claims).WithOne().HasForeignKey(uc => uc.UserId).IsRequired(); b.HasMany(u => u.Logins).WithOne().HasForeignKey(ul => ul.UserId).IsRequired(); b.HasMany(u => u.Roles).WithOne().HasForeignKey(ur => ur.UserId).IsRequired(); ); builder.Entity<TRole>(b => b.HasKey(r => r.Id); b.HasIndex(r => r.NormalizedName).HasName("RoleNameIndex"); b.ToTable("AspNetRoles"); b.Property(r => r.ConcurrencyStamp).IsConcurrencyToken(); b.Property(u => u.Name).HasMaxLength(256); b.Property(u => u.NormalizedName).HasMaxLength(256); b.HasMany(r => r.Users).WithOne().HasForeignKey(ur => ur.RoleId).IsRequired(); b.HasMany(r => r.Claims).WithOne().HasForeignKey(rc => rc.RoleId).IsRequired(); ); builder.Entity<TUserClaim>(b => b.HasKey(uc => uc.Id); b.ToTable("AspNetUserClaims"); ); builder.Entity<TRoleClaim>(b => b.HasKey(rc => rc.Id); b.ToTable("AspNetRoleClaims"); ); builder.Entity<TUserRole>(b => b.HasKey(r => new r.UserId, r.RoleId ); b.ToTable("AspNetUserRoles"); ); builder.Entity<TUserLogin>(b => b.HasKey(l => new l.LoginProvider, l.ProviderKey ); b.ToTable("AspNetUserLogins"); ); builder.Entity<TUserToken>(b => b.HasKey(l => new l.UserId, l.LoginProvider, l.Name ); b.ToTable("AspNetUserTokens"); );

   public class ApplicationDbContext 
    : IdentityDbContext

    public ApplicationDbContext()
        : base("DefaultConnection")
    
    

    static ApplicationDbContext()
    
        Database.SetInitializer<ApplicationDbContext>(new ApplicationDbInitializer());
    

    public static ApplicationDbContext Create()
    
        return new ApplicationDbContext();
    

    // Add additional items here as needed

基于源代码,如果我们想将IdentityDbContext与我们的DbContext合并,我们有两个选择: 第一选择: 创建一个DbContext,它继承自IdentityDbContext并可以访问这些类。

    public class ApplicationDbContext : IdentityDbContext
        
        public ApplicationDbContext(): base("DefaultConnection")
        
        

        protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
        
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<IdentityUser>().ToTable("user");
            modelBuilder.Entity<ApplicationUser>().ToTable("user");

            modelBuilder.Entity<IdentityRole>().ToTable("role");
   

以上是关于ASP.NET身份DbContext混淆的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core Web API 身份验证

将 ASP.NET 标识集成到现有 DbContext 中

在 DDD 中公开 ASP.NET 身份服务

在 ASP.NET Core Authorize-Attribute 中使用带有 DbContext 的存储库:“无法访问已处置的对象”

使用 Identity Server 4 和 ASP.NET Identity 添加外部登录

ASP.NET 5 多个 dbcontext 问题