Search code examples
asp.netasp.net-mvcoracleasp.net-identity

ASP.NET MVC 5 Storing identity users in Oracle database


I'm pretty new to developing ASP.NET apps, I started a new project and I'm using a Oracle DB with the ODP and OLAC plugins. I set up my connection string and I can see the database under the Server Explorer.

Now I want the Identity users to be stored on my DB too, but I cannot find where they are being stored right now. The app_data folder is empty, there are no .mdf files anywhere, my connection string is the Oracle connection string; but when I set up the IdentityDBContext to use my own connection string I get an error saying "The entity type ApplicationUser is not part of the model for the current context." I'm using a database-first approach:

This is the autogenerated code for my DB context:

public partial class ActivoContext : DbContext
{
    public ActivoContext()
        : base("name=ActivoContext")
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        throw new UnintentionalCodeFirstException();
    }
......

This is the Identity code generated by the project, I just changed the connection string:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("name=ActivoContext", throwIfV1Schema: false)
    {
    }

    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }
}

web.config file:

<connectionStrings>
  <add name="ActivoContext" connectionString="metadata=res://*/Activo.csdl|res://*/Activo.ssdl|res://*/Activo.msl;provider=Oracle.ManagedDataAccess.Client;provider connection string=&quot;DATA SOURCE=localhost:1521/xe;PASSWORD=activos;USER ID=ACTIVOS&quot;" providerName="System.Data.EntityClient" />
</connectionStrings>

EDIT So I realized the problem is having two different Contexts using the same connection string. Because of this, only one shows up and the other one doesnt work: the auto-generated db-first ActivoContext shows up and ApplicationDbContext doesnt. How should I go about merging these two or making them work together? I can't modify DbContext cause its auto-generated...


Solution

  • Finally got Identity 2.0 to work with my Oracle DB. Here's what I did:

    The following steps work if you don't want to make any changes to the default IdentityUser (ex. if you're ok with having a char ID instead of int or long) and just want the tables on your existing Oracle schema.

    1) Create Identity tables on Oracle. You can change the table names if you want to, just make sure to include the necessary columns for Identity to work with it. You can also add any extra columns you may need on your application (script originally found on Devart, I copied it to a gist in case URL breaks):

    Gist here

    2) If you're using an EDMX file, you need to add a new connection string cause the one that gets generated automatically won't work, you need a standard connection string. Try following this template:

    <add name="IdentityContext" connectionString="Data Source=localhost:1521/xe;PASSWORD=password;USER ID=username;" providerName="Oracle.ManagedDataAccess.Client" />
    

    3) Tell your ApplicationDbContext to use your new connectionString

    public ApplicationDbContext()
    : base("IdentityContext", throwIfV1Schema: false)
    {
    }
    

    4) Tell Identity to use your existing schema and tables. Add this method inside the ApplicationDbContext definition found in IdentityModels.cs:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
    base.OnModelCreating(modelBuilder); // MUST go first.
    
    modelBuilder.HasDefaultSchema("YOUR_SCHEMA"); // Use uppercase!
    
    modelBuilder.Entity<ApplicationUser>().ToTable("AspNetUsers");
    modelBuilder.Entity<IdentityRole>().ToTable("AspNetRoles");
    modelBuilder.Entity<IdentityUserRole>().ToTable("AspNetUserRoles");
    modelBuilder.Entity<IdentityUserClaim>().ToTable("AspNetUserClaims");
    modelBuilder.Entity<IdentityUserLogin>().ToTable("AspNetUserLogins");
    }
    

    5) Rebuild and thats it!