drovani
drovani

Reputation: 938

Classes inherited from Identity objects not included in Code First Migrations

In order to fully customize the ASP.NET Identity framework, I have inherited classes from all six of the Identity classes:

public class VigilUserRole : IdentityUserRole<Guid>
public class VigilUserLogin : IdentityUserLogin<Guid>
public class VigilUserClaim : IdentityUserClaim<Guid>
public class VigilUser : IdentityUser<Guid, VigilUserLogin, VigilUserRole, VigilUserClaim>
public class VigilRole : IdentityRole<Guid, VigilUserRole>
public class VigilDataContext : IdentityDbContext<VigilUser, VigilRole, Guid, VigilUserLogin, VigilUserRole, VigilUserClaim>

With nothing else in the project, I attempted to add an initial migration. All of the default AspNet* tables are the only tables included in the migration.

    public override void Up()
    {
        CreateTable(
            "dbo.AspNetRoles",
            c => new
                {
                    Id = c.Guid(nullable: false),
                    Name = c.String(nullable: false, maxLength: 256),
                })
            .PrimaryKey(t => t.Id)
            .Index(t => t.Name, unique: true, name: "RoleNameIndex");

        CreateTable(
            "dbo.AspNetUserRoles",
            c => new
                {
                    UserId = c.Guid(nullable: false),
                    RoleId = c.Guid(nullable: false),
                    VigilUserRoleId = c.Guid(nullable: false),
                })
            .PrimaryKey(t => new { t.UserId, t.RoleId })
            .ForeignKey("dbo.AspNetRoles", t => t.RoleId, cascadeDelete: true)
            .ForeignKey("dbo.AspNetUsers", t => t.UserId, cascadeDelete: true)
            .Index(t => t.UserId)
            .Index(t => t.RoleId);

        CreateTable(
            "dbo.AspNetUsers",
            c => new
                {
                    Id = c.Guid(nullable: false),
                    Email = c.String(maxLength: 256),
                    EmailConfirmed = c.Boolean(nullable: false),
                    PasswordHash = c.String(),
                    SecurityStamp = c.String(),
                    PhoneNumber = c.String(),
                    PhoneNumberConfirmed = c.Boolean(nullable: false),
                    TwoFactorEnabled = c.Boolean(nullable: false),
                    LockoutEndDateUtc = c.DateTime(),
                    LockoutEnabled = c.Boolean(nullable: false),
                    AccessFailedCount = c.Int(nullable: false),
                    UserName = c.String(nullable: false, maxLength: 256),
                })
            .PrimaryKey(t => t.Id)
            .Index(t => t.UserName, unique: true, name: "UserNameIndex");

        CreateTable(
            "dbo.AspNetUserClaims",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                    UserId = c.Guid(nullable: false),
                    ClaimType = c.String(),
                    ClaimValue = c.String(),
                })
            .PrimaryKey(t => t.Id)
            .ForeignKey("dbo.AspNetUsers", t => t.UserId, cascadeDelete: true)
            .Index(t => t.UserId);

        CreateTable(
            "dbo.AspNetUserLogins",
            c => new
                {
                    LoginProvider = c.String(nullable: false, maxLength: 128),
                    ProviderKey = c.String(nullable: false, maxLength: 128),
                    UserId = c.Guid(nullable: false),
                })
            .PrimaryKey(t => new { t.LoginProvider, t.ProviderKey, t.UserId })
            .ForeignKey("dbo.AspNetUsers", t => t.UserId, cascadeDelete: true)
            .Index(t => t.UserId);

    }

I even tried overriding the OnModelCreating method, explicitly ignoring the Identity tables and registering the Vigil classes.

    protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
    {
        modelBuilder.Ignore(new Type[] { typeof(IdentityUser), typeof(IdentityRole), typeof(IdentityUserClaim), typeof(IdentityUserRole), typeof(IdentityUserLogin) });
        modelBuilder.RegisterEntityType(typeof(VigilUser));
        modelBuilder.RegisterEntityType(typeof(VigilUserRole));
        modelBuilder.RegisterEntityType(typeof(VigilUserClaim));
        modelBuilder.RegisterEntityType(typeof(VigilUserLogin));
        modelBuilder.RegisterEntityType(typeof(VigilRole));

        base.OnModelCreating(modelBuilder);
    }

What am I missing that the Vigil classes are not being recognized in the migration, but the Identity class (mapped to AspNet tables) are being included? I have even tried replacing the TKey type with an int, but receive the same result.

Solution can also be downloaded from my sandbox repo, which includes a history of various failed attempts to resolve the issue.

Upvotes: 1

Views: 236

Answers (1)

tmg
tmg

Reputation: 20383

Your ApplicationDbContext inherits from IdentityDbContext. Inside OnModelCreating method of your ApplicationDbContext last line (base.OnModelCreating(modelBuilder)) you call the OnModelCreating method of base class (source here) which contains

modelBuilder.Entity<TUser>().ToTable("AspNetUsers");
modelBuilder.Entity<TUserRole>().HasKey(r => new { r.UserId, r.RoleId })
            .ToTable("AspNetUserRoles");
modelBuilder.Entity<TUserLogin>()
            .HasKey(l => new { l.LoginProvider, l.ProviderKey, l.UserId })
            .ToTable("AspNetUserLogins");
modelBuilder.Entity<TUserClaim>()
            .ToTable("AspNetUserClaims");
modelBuilder.Entity<TRole>()
            .ToTable("AspNetRoles");

so no matter what you did above you overwrite it.

Try to move this line on top before your custom code.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {                       
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<VigilUser>().ToTable("VigilUser");    
            modelBuilder.Entity<VigilRole>().ToTable("VigilRole");
            modelBuilder.Entity<VigilUserRole>().ToTable("VigilUserRole");
            modelBuilder.Entity<VigilUserClaim>().ToTable("VigilUserClaim");
            modelBuilder.Entity<VigilUserLogin>().ToTable("VigilUserLogin");
        }

Upvotes: 1

Related Questions