0

I'm working on small asp.net core project, where I'm using EF core with SQL server.

So far I've got following configuration:

  1. Db context for my domain entities:
    public class AppDbContext: DbContext
    {
        public AppDbContext(DbContextOptions<AppDbContext> options)
        : base(options) { }

        public DbSet<Request> Requests { get; set; }
        public DbSet<Ticket> Tickets { get; set; }
        public DbSet<Project> Project { get; set; }
        public DbSet<QA> QA { get; set; }
        public DbSet<ProjectOwner> ProjectOwner { get; set; }
    }
  1. AppIdentityDbContext scaffolded automatically by Visual Studio:

    public class AppIdentityDbContext : IdentityDbContext
    {
        public AppIdentityDbContext(DbContextOptions<AppIdentityDbContext> options)
            : base(options)
        { }
            public DbSet<IdentityUser> User { get; set; }
        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);
        }
    }

Can I put these contexts in single context? As far as I know they inherit from different base contexts, so my solution rely on two separate contexts so far. I'm not sure if there is any advantage to keep two contexts rather than one, especially in case of small application. After reading this thread I don't think my solution need two of them. As a beginner I'd like to keep it super simple, so how could I achieve it?

Many thanks!

MonTom
  • 35
  • 1
  • 7

1 Answers1

1

You can base your application DbContext off IdentityDbContext to serve the standard EF integrated authentication, or provide your own authentication implementation that uses your regular DbContext-based application context. However, I generally recommend leaving these concerns separate. This is an example of employing a bounded DbContext. The IdentityDbContext serves its purpose without polluting it with concerns of the application data. Often though you may want to "link" data rows to a User (i.e. CreatedBy/ModifiedBy) which then raises the question of having user apparently in a separate DbContext. For this I will declare a simplified User entity to reference in the application DbContext definition containing just the properties that are relevant for the typical usage.

Given a table called Users with references for credentials, passwords/tokens etc. but also might have application specific details:

The AppIdentityContext sees an IdentityUser which exposes the User ID, credentials, etc. needed for authenticating and authorizing a user.

The AppContext sees a User which exposes the User ID, e-mail, and any app details appended or linked to the user table, but exposes no Authentication/Authorization details.

Both entities are linked to the same table, but serve the separate concerns.

It doesn't make sense to be able to have code like:

var order = _context.Orders.Where(x => x.OrderId == orderId).Select(x => new 
{
    x.OrderId,
    x.OrderNumber,
    x.CreatedBy.UserId,
    x.CreatedBy.Credential.PasswordHash // <- Not an application concern.
}).Single();

Whether intentional by a dev or accidental, application concerns for a User should not have the potential to expose or tamper with details relating to authentication or authorization. This would be especially important if the code was doing something like serializing entity graphs.

If I want to support something more administrative within the application, or a separate app for managing users, that would be its own DbContext definition again with higher exposure for the fields across both application and Auth concerns. This admin context & functionality would expose both application and authentication/authorization details:

The AppAdminContext sees a FullAppUser which exposes the User ID, e-mail, all app details as well as the Authentication/Authorization details. Functionality that can create/edit users, adjust roles, reset passwords, as well as administer application specific details would use this DbContext and the full user to manage all aspects of the user.

It may seem like overkill for a simple app but it is a good practice IMO to demonstrate the separation of concerns.

Steve Py
  • 26,149
  • 3
  • 25
  • 43