扩展IdentityUser后无法获取登录用户完整数据的问题排查
我来帮你搞定这个空引用的问题,核心是你的Identity配置和EF实体映射出了纰漏,一步步来修复:
你现在的核心问题在于IdentityDbContext的泛型类型配置错误,加上对AppUser实体的不必要重写,导致EF无法把你扩展的AppUser和Identity默认的用户表关联起来,自然查不到用户的扩展数据。
1. 修正AppDbContext的继承关系
你当前继承的是IdentityDbContext<IdentityUser>,但你实际扩展的是AppUser,必须把泛型参数改成AppUser,这样EF才会把AppUser作为Identity用户表的实体(对应数据库里的AspNetUsers表):
public class AppDbContext : IdentityDbContext<AppUser> { // 将泛型参数改为AppUser public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { } public DbSet<Lesson> lesson { get; set; } public DbSet<Message> message { get; set; } public DbSet<Assignment> assignment { get; set; } // 注意:不需要单独定义DbSet<AppUser>! // IdentityDbContext<AppUser>已经自带了对用户表的映射,AspNetUsers表会自动关联AppUser // public DbSet<AppUser> appUser { get; set; } // 这行可以直接删除 }
2. 简化AppUser实体,移除不必要的重写
IdentityUser已经自带Id、Email、PhoneNumber、UserName这些属性,你完全不需要手动重写它们,手动添加[Key]还可能和Identity的默认主键配置冲突,简化后的AppUser应该是:
public class AppUser : IdentityUser { // 只保留你自己的扩展字段即可 public string Name { get; set; } public string Photo { get; set; } public string Description { get; set; } }
3. 修正TeachersVM中的用户查询逻辑
现在DbContext已经正确关联AppUser,你可以直接通过_context.Users(IdentityDbContext自带的用户集合)来查询AppUser,而不是之前的_context.appUser:
public class TeachersVM { private AppDbContext _context; public TeachersVM(AppDbContext context) { _context = context; } public string UserID { get; set; } public AppUser appUser { get; set; } public List<Lesson> lessons { get; set; } // public List<Message> messages { get; set; } // public List<Assignment> assignments { get; set; } public TeachersVM Init(string userId) { // 使用_context.Users查询AppUser appUser = _context.Users.FirstOrDefault(l => l.Id == userId); lessons = _context.lesson.Where(l => l.TechID == userId).ToList(); // messages = _context.message.Where(l => l.TechID == userId).ToList(); // assignments = _context.assignment.Where(l => l.TechID == userId).ToList(); return this; } }
4. 控制器中直接获取AppUser类型的用户
之前你用IdentityUser user = await userManager.FindByEmailAsync(model.Email);,这样只能拿到基础的IdentityUser,无法获取扩展字段,应该改成AppUser类型:
// 直接获取AppUser,这样就能拿到所有扩展字段 AppUser user = await userManager.FindByEmailAsync(model.Email); return View("TchrProfile", teachersVM.Init(user.Id));
5. 更新数据库迁移
修改完DbContext和实体后,需要重新生成迁移并更新数据库,让EF把AspNetUsers表更新为包含你的扩展字段:
Add-Migration UpdateAppUser Update-Database
- 实体命名规范:建议把
lesson、message、assignment改成复数形式(Lessons、Messages、Assignments),符合EF的常规命名习惯。 - 查询优化:如果Lesson、Message等和AppUser有关联,可以用
Include来一次性加载关联数据,比如_context.Users.Include(u => u.Lessons).FirstOrDefault(...),避免多次查询数据库。
内容的提问来源于stack exchange,提问作者Medoo

