Search code examples
asp.net.netentity-frameworkasp.net-mvc-4asp.net-identity

Asp.net identity context is not mapping without custom classes


So, I have changed my application so that I may use an integer primary key on my tables (a horrid process by the way). Everything works fine. Consider my ApplicationDbContext class:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser, CustomRole, int, CustomUserLogin, CustomUserRole, CustomUserClaim>, IIDentityContext
{
    public ApplicationDbContext()
        : base("OwinTestDefault")
    {
        Database.SetInitializer<ApplicationDbContext>(null);
    }
    ...
}

Now consider, for example, my user login class here, in its entirety:

public class CustomUserLogin : IdentityUserLogin<int>
{
}

It seemed silly to have to make a class just for this, and that I should be able to just replace any instance of this with IdentityuserLogin<int> in the code, resulting in this now:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser, CustomRole, int, IdentityUserLogin<int>, CustomUserRole, CustomUserClaim>, IIDentityContext
{
    public ApplicationDbContext()
        : base("OwinTestDefault")
    {
        Database.SetInitializer<ApplicationDbContext>(null);
    }
    ...
}

However, bafflingly, it now doesn't work and throws the error:

The type 'Microsoft.AspNet.Identity.EntityFramework.IdentityUserLogin`1[System.Int32]' was not mapped. Check that the type has not been explicitly excluded by using the Ignore method or NotMappedAttribute data annotation. Verify that the type was defined as a class, is not primitive or generic, and does not inherit from EntityObject.`

Searching around, some people have run into this when they have changed their table names, but I have not done this, and regardless, overriding OnModelCreating and explicitly mapping everything I can (table name, keys, column names and properties) has no effect and it still complains it isn't mapped. Plus, looking at the source code of the base classes on GitHub, the mapping should be fine anyways.

Any ideas?


Solution

  • It seems that in Entity Framework, you cannot map multiple levels of generic types, as EF cannot create a proxy from this. Props to this answer: Are generic classes not supported as models in Entity Framework?

    If you consider IdentityDbContext.cs in the source code, this line:

    public virtual IDbSet<TRole> Roles { get; set; }
    

    is really:

    public virtual IDbSet<IdentityRole<int, IdentityUserRole<int>> Roles { get; set; }
    

    It needs to be able to make a proxy out of this very type as a whole, thus why using a derived base class works.