Cannot use built in Identity classes with database-first development

204 views Asked by At

I'm stuck in a weird issue. I have to start an ASP.NET MVC project with a database-first approach. I want to use built-in identity for authentication and authorization.

I have successfully added repository pattern in a class library project with a model and other classes.

Added a reference to my ASP.NET MVC project and changed the connection string of the project along with context

This is the connection string of both projects

<add name="DoctorsDBEntities"
     connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;
                       provider=System.Data.SqlClient;
                       provider connection string=&quot;data source=(LocalDb)\MSSQLLocalDB;initial catalog=DoctorsDB;
                       integrated security=True;
                       MultipleActiveResultSets=True;
                       App=EntityFramework&quot;"
    providerName="System.Data.EntityClient" />

Following is the code of ApplicationUser and DoctorsDbContext class

public class ApplicationUser : IdentityUser
{
    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here
        return userIdentity;
    }
}

public class DoctorsDbContext : IdentityDbContext<ApplicationUser>
{
    static DoctorsDbContext()
    {

        Database.SetInitializer<IdentityDbContext>(null);

        Database.SetInitializer<DoctorsDbContext>(null);

    }
    public DoctorsDbContext()
        : base("DoctorsDBEntities", throwIfV1Schema: false)
    {
        Database.SetInitializer<IdentityDbContext>(null);
        Database.SetInitializer<DoctorsDbContext>(null);
    }

    public static DoctorsDbContext Create()
    {
        return new DoctorsDbContext();
    }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<IdentityUser>()
                       .ToTable("dbo.AspNetUsers");
        modelBuilder.Entity<ApplicationUser>()
                      .ToTable("dbo.AspNetUsers");

        modelBuilder.Entity<IdentityRole>()
                     .ToTable("dbo.AspNetRoles");
        //modelBuilder.Entity<ApplicationRole>()
                     //.ToTable("dbo.AspNetRoles");

        modelBuilder.Entity<IdentityUserClaim>().ToTable("dbo.AspNetUserClaims");

        modelBuilder.Entity<IdentityUserRole>().ToTable("dbo.AspNetUserRoles");
        modelBuilder.Entity<IdentityUserRole>().HasKey((IdentityUserRole r) => new { UserId = r.UserId, RoleId = r.RoleId }).ToTable("dbo.AspNetUserRoles");

        modelBuilder.Entity<IdentityUserLogin>().ToTable("dbo.AspNetUserLogins");
    }

Now getting this error

enter image description here

2

There are 2 answers

3
Mostafa Esmaeili On

If I understand you correctly, You use default Microsoft identity classes. And you want to Control it by your db first context. If it is Ok THEN :

You should Inherit from IdentityDbContext<ApplicationUser> instead Dbcontext

public class DoctorsDbContext : IdentityDbContext<ApplicationUser>
{


    static DoctorsContext()
    {

        Database.SetInitializer<IdentityDbContext>(null);

        Database.SetInitializer<DoctorsDbContext>(null);

    }

    public DoctorsDbContext()
        : base("Name=nameOfConnectionString")
    {
       Database.SetInitializer<IdentityDbContext>(null);

       Database.SetInitializer<DoctorsDbContext >(null);
    }

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<IdentityUser>()
                       .ToTable("dbo.AspNetUsers");
        modelBuilder.Entity<ApplicationUser>()
                      .ToTable("dbo.AspNetUsers");

        modelBuilder.Entity<IdentityRole>()
                     .ToTable("dbo.AspNetRoles");
        modelBuilder.Entity<ApplicationRole>()
                     .ToTable("dbo.AspNetRoles");

        modelBuilder.Entity<IdentityUserClaim>().ToTable("dbo.AspNetUserClaims");

        modelBuilder.Entity<IdentityUserRole>().ToTable("dbo.AspNetUserRoles");
        modelBuilder.Entity<IdentityUserRole>().HasKey((IdentityUserRole r) => new { UserId = r.UserId, RoleId = r.RoleId }).ToTable("dbo.AspNetUserRoles");

        modelBuilder.Entity<IdentityUserLogin>().ToTable("dbo.AspNetUserLogins");
             }

and ApplicationUser :

public class ApplicationUser : IdentityUser
{
    GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here
        return userIdentity;
    }

} 

and replace all Dbcontext in identity Generated classes and methods with DoctorsDbContext .

0
Asfar Irshad On

I was doing this wrong. Was using the connection string was of Entity Framework which is not supposed to work for Identity.

Simply added another connection string for identity and it worked

<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=DoctorsDB;Integrated Security=True" providerName="System.Data.SqlClient" />