Separating Data Access in Asp.Net Core 2
Tags: aspnetcore20, identity, dataaccess
Published: 2019-08-05 21:52:40

---
title: Separating Data Access in Asp.Net Core 2
published: true
description: Separating Data Access in Asp.Net Core 2
tags: Asp.Net Core 2.0, Identity, Data Access
---

<link rel="canonical" href="https://www.pmichaels.net/2018/06/30/separating-data-access-in-asp-net-core-2/" />

In Asp.Net Core 2, like in previous incarnations of Asp.Net there is a wizard that gives you a head-start with a a simple user log-in / registration system:

<a href="https://www.pmichaels.net/wp-content/uploads/2018/06/aspnet-core2-id-4.png"><img src="https://www.pmichaels.net/wp-content/uploads/2018/06/aspnet-core2-id-4.png" alt="" width="780" height="549" class="alignnone size-full wp-image-3377" /></a>

If you set-up a new project using the wizard to create an individual user account, you may notice in the generated project, the lack of seemingly any code to achieve this.  The reason being that all the code for the identity system is tucked away inside <a href="https://docs.microsoft.com/en-us/aspnet/core/security/authentication/scaffold-identity?view=aspnetcore-2.1&tabs=visual-studio">the razor pages</a>.  I see this as mainly a good thing, but with one exception*: I don't like having the DB access code inside the main web project; it makes DI very difficult.  So this is the story of how you can extricate the DB Access portion of this into a separate project.

<h1>Context</h1>

The crux of this is to move the context into a separate project; so let's start with a new project:

<a href="https://www.pmichaels.net/wp-content/uploads/2018/06/aspnet-core2-id-1.png"><img src="https://www.pmichaels.net/wp-content/uploads/2018/06/aspnet-core2-id-1.png" alt="" width="384" height="261" class="alignnone size-full wp-image-3371" /></a>

If you just want the identity access, then you'll only need to move the 
ApplicationIdentityDbContext, however, in real life, you're probably going to end up with two contexts:

<a href="https://www.pmichaels.net/wp-content/uploads/2018/06/aspnet-core2-id-2.png"><img src="https://www.pmichaels.net/wp-content/uploads/2018/06/aspnet-core2-id-2.png" alt="" width="383" height="230" class="alignnone size-full wp-image-3370" /></a>

The contexts themselves need to be separate because the identity context inherits from IdentityDbContext**:

    public class ApplicationIdentityDbContext : IdentityDbContext
    {    
        public     ApplicationIdentityDbContext(DbContextOptions<ApplicationIdentityDbContext> options)
        : base(options)
        {
        }
    }

Your second context should just inherit from DbContext.

<h1>NuGet</h1>

There's a couple of gotcha's with this; but the libraries that you need in the DataAccess project are:

    Install-Package Microsoft.EntityFrameworkCore
    Install-Package Microsoft.EntityFrameworkCore.SqlServer
    Install-Package Microsoft.Entensions.Identity.Stores


<h1>Startup.cs</h1>

Finally, you'll need to change the DI to register both contexts:

    services.Configure<IdentityOptions>(options =>
    {
        options.Password.RequireNonAlphanumeric = false;                
    });
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDbContext<ApplicationIdentityDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
     
    services                
        .AddDefaultIdentity<IdentityUser>()
        .AddEntityFrameworkStores<ApplicationIdentityDbContext>();


I'm using SqlServer here, so if you're not then you'll obviously need to change the bits around that.  You'll notice that I switched the requirement to have your password have a non-alphanumeric character - especially for development, this can be annoying.  I also don't necessarily accept that it increases security for the site***.

<h1>Migrations</h1>

Now that you have multiple contexts, when you add a migration, you'll need to specify the context to use; for example:

    Add-Migration "InitialUserSetup" -context ApplicationIdentityDbContext

The same is true for Update-Database:

    Update-Database -context ApplicationIdentityDbContext


<h1>Footnotes</h1>

\* Okay - there may be other pitfalls; but if this works for 60% of the authentication cases, why not have it all inside a magic black box?  When you need something more customised, you can always rip this out and replace it with your own.

** There's nothing stopping you having the main DbContext inherit from IdentityDbContext, or just using IdentityDbContext as the main context.

*** Obviously, it does improve security for the site if everyone is using a 20 digit code and they start using non-alpha-numeric characters in that code; however, if they're using a password manager, they probably are already generating such a code, and if not then you'll just force "Password123" to "!Password123", so you probably don't gain much!


<h1>References</h1>

<a href="https://github.com/aspnet/EntityFrameworkCore/issues/7891">https://github.com/aspnet/EntityFrameworkCore/issues/7891</a>

<a href="https://exceptionnotfound.net/whats-this-and-can-i-delete-it-examining-a-default-asp-net-core-mvc-project/">An excellent intro to Asp.Net Core 2 default structure</a>

Originally posted <a href="https://www.pmichaels.net/2018/06/30/separating-data-access-in-asp-net-core-2/">here</a>.