Customizando Nomes de Tabelas e Campos no ASP.NET Identity

O ASP.NET Identity possui um padrão de nomenclatura para suas tabelas e campos, muitas vezes é necessário customizar este padrão para atender as necessidades da aplicação, confira como é simples realizar esta tarefa.

Como apresentado aqui algumas vezes, o ASP.NET Identity é um componente muito completo e simples de customizar, ele é escrito baseado no conceito Code-First e sua arquitetura é bem aberta possibilitando a customização de funcionalidades, comportamentos e até mesmo fonte de dados.

As tabelas que o ASP.NET Identity cria automaticamente segue o mesmo processo de qualquer desenvolvimento Code-First, permitindo que o desenvolvedor mapeie na configuração do DbContext toda a modelagem da base que será criada.

Vamos abordar de forma muito simples e pontual como realizar este processo partindo do pré-suposto que sua aplicação foi criada com base no template de aplicação ASP.NET MVC já com o ASP.NET Identity configurado. Independente deste fato, o que é realmente necessário fazer é editar o contexto do ASP.NET Identity.

Uma dica válida para qualquer situação é manter sempre o contexto do ASP.NET Identity separado do contexto da aplicação.

Iremos trabalhar também com a hipótese de customização do IdentityUser através de sua classe derivada ApplicationUser. Vamos ao código.

public class ApplicationUser : IdentityUser
{
    public string Apelido { get; set; }
}

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("DefaultConnection")
    {
    }

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

        modelBuilder.Entity<IdentityUser>()
            .ToTable("Usuarios")
            .Property(p => p.Id)
            .HasColumnName("UsuarioId");

        modelBuilder.Entity<ApplicationUser>()
            .ToTable("Usuarios")
            .Property(p => p.Id)
            .HasColumnName("UsuarioId");

        modelBuilder.Entity<IdentityUserRole>()
            .ToTable("UsuarioPapel");

        modelBuilder.Entity<IdentityUserLogin>()
            .ToTable("Logins");

        modelBuilder.Entity<IdentityUserClaim>()
            .ToTable("Claims");

        modelBuilder.Entity<IdentityRole>()
            .ToTable("Papeis");
    }
}

Na classe ApplicationUser realizamos uma pequena customização adicionando um novo campo (Apelido), apenas para enfatizar a situação.

Na classe ApplicationDbContext repare que ela herda de IdentityDbContext, que é a real classe de contexto do ASP.NET Identity onde ela internamente herda de DbContext.

A ideia de existir a classe ApplicationDbContext é justamente fornecer um contexto para customização, uma vez que a classe IdentityDbContext faz parte dos assemblies do ASP.NET Identity e não é possível ser alterada.

Baseado no conceito da herança o que basicamente fizemos foi sobrescrever o método OnModelCreating da classe base para alterarmos os padrões de nomenclatura. Utilizamos Fluent API para realizar esse mapeamento trocando os nomes das tabelas e campos.

Essa troca não impacta no funcionamento interno do ASP.NET Identity, pois as classes internas permanecem intactas, apenas o mapeamento do modelo objeto / relacional foi modificado e a aplicação irá seguir o que a modelagem manda.


modelBuilder.Entity<IdentityUser>()
    .ToTable("Usuarios")
    .Property(p => p.Id)
    .HasColumnName("UsuarioId");

modelBuilder.Entity<ApplicationUser>()
    .ToTable("Usuarios")
    .Property(p => p.Id)
    .HasColumnName("UsuarioId");

Repare que as duas classes (IdentityUser, ApplicationUser) foram mapeadas para mesma tabela, pois só assim seria possível mapear a classe de usuários e ao mesmo tempo aplicar as customizações, no final tudo vira uma única tabela com informações de ambas as classes.

ASP.NET Identity Tabelas e Campos Customizados

Detalhes adicionais

  • É possível utilizar todos os recursos do Fluent API nessa abordagem, sendo possível modificar tipo dos campos, inserir índices, criar novos relacionamentos, mapear novas tabelas e etc.
  • É possível realizar todo este mapeamento em uma outra classe e configurar esta classe no contexto (assim como fazemos com as nossas entidades no Fluent API).

Simples?
Agora é possível incorporar o ASP.NET Identity ao seu modelo já existente de base de usuários, a única premissa é que todas as tabelas e campos do ASP.NET Identity sejam representados (mapeados) de alguma forma no banco de dados existente.

Vamos continuar a enriquecer este artigo participando nos comentários abaixo com dúvidas, complementos e feedbacks.

Referências

Este artigo foi escrito durante minha participação na Campus Party 2015 #CPBR8