How do I read from the dbo.AspNetUsers table?

Viewed 3759

I want to retrieve data from the Identity-table dbo.AspNetUsers, but I haven't figured out how to query it.

This is my db-context:

public class ProjectsDbContext : IdentityDbContext<IdentityUser>
{
    public ProjectsDbContext(DbContextOptions<ProjectsDbContext> options) : base(options) { }

    public DbSet<Project> Projects { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        if (modelBuilder == null)
        {
            throw new NullReferenceException();
        }

        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Project>()
            .HasMany(c => c.ChildProjects)
            .WithOne(p => p.ParentProject)
            .HasForeignKey(p => p.ParentProjectId);
    }
}

This is my User-class:

public class User : IdentityUser
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

This is the query I have, which doesn't work:

List<User> projectOwners = await db.Users.ToListAsync();

The error message I get is:

Cannot implicitly convert type 'System.Collections.Generic.List<Microsoft.AspNetCore.Identity.IdentityUser>' to 'System.Collections.Generic.List<Projects.Models.User>'

If I replace List<User> with var in the query, the error goes away, but the collection I get does not contain any of the properties from my own User-class.

How do I access the AspNetUsers, including my own extra properties defined in User?

2 Answers

With EF Core with, the table AspNetUsers is mapped to the Users DbSet, so you can easily reference it by

db.Users

If you customise the AspNetTable, adding your own fields, such as FirstName, LastName, then you need the to derive from IdentityUser as per @timur's answers, but you should still be able reference the table with just db.Users

Assumig you're setting your project up more or less according to standard boilerplate, I believe you can cast override type of your identity user like so:

Startup.cs

 public void ConfigureServices(IServiceCollection services)
        {
            // pretty standard initialisation so far
            services.AddDbContext<ProjectsDbContext>(options =>
                options.UseSqlServer(
                    Configuration.GetConnectionString("DefaultConnection")));
            services.AddDefaultIdentity<User>(options => options.SignIn.RequireConfirmedAccount = false) // this is the key - put your custom User Identity here
                .AddEntityFrameworkStores<ProjectsDbContext>();
        }

ProjectsDbContext.cs

public class User : IdentityUser
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
    public class ProjectsDbContext: IdentityDbContext<User> // this is your custom User type
    {
        public ProjectsDbContext(DbContextOptions<ProjectsDbContext> options)
            : base(options)
        {
        }
    }

then, since you are changing the data model, you will need to migrate the schema:

PM> Add-Migration change_IdentityUser
PM> Update-Database

you will notice the migration adds your custom fields to the table:

public partial class change_IdentityUser : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.AddColumn<string>(
                name: "FirstName",
                table: "AspNetUsers",
                nullable: true);

            migrationBuilder.AddColumn<string>(
                name: "LastName",
                table: "AspNetUsers",
                nullable: true);
        } 
.......

and finally, all references to SignInManager/UserManager and other helpers will need to be updated with new generic type parameter:

_LoginPartial.cshtml

@inject SignInManager<User> SignInManager
@inject UserManager<User> UserManager
Related