Search code examples
c#asp.net-coreentity-framework-coreinversion-of-control

Accessing the DBContext from classes in 2 different projects when one reads from DBContextBase and the other from DomainDBContext


I have a shared project that I put my shared and base logic in to reuse in other projects and a Normal asp.net core project on top of it.

In the Shared base project I have:

class DbContextBase : DbContext
{
  public DbSet<ActivityLog> ActivityLogs { get; set; }
  public DbSet<Event> Events { get; set; }
  SaveChanges(...)
}

class MyEventProcessor
{
   private readonly DbContextBase _databaseContext;
   public MyEventProcessor(DbContextBase databaseContext)
   {
      _databaseContext=databaseContext;
   }
   public void AddEvent(Event e){}
   public void ProcessEvent(Event e){}
}

In the .net core webApi one I have my domain specific logic

class MyDomainDbContext : DbContextBase
{
  public DbSet<User> Users{ get; set; }
}

class UserRepository
{
     private readonly MyDomainDbContext _databaseContext;
     public UserRepository(MyDomainDbContext databaseContext){_databaseContext=databaseContext;}
}

public class Startup
   {
      public Startup(IConfiguration configuration)
      {
        services.AddDbContext<MyDomainDbContext>([options]);
        services.AddScoped<UserRepository>();
        services.AddScoped<EventProcessor>();
      }
   }

The problem is, this way it fails on startup not being able to find DbContextBase because it is not registered. I thought of changing the registeration to an interface like below, but then obviously I won't have access to my domain's DbSets in my repositories.

services.AddDbContext<IDbContextBase,MyDomainDbContext>([options]);

So the question is, how do I set this so that MyEventProcessor and UserRepository can read and write into the same Database context.


Solution

  • You need to register both types: DbContextBase and MyDomainDbContext, however the point is to reuse the same instance for both cases, in order to achieve that you can register them in a following way:

    services.AddDbContext<MyDomainDbContext>([options]);
    services.AddScoped<DbContextBase, MyDomainDbContext>(sp => sp.GetRequiredService<MyDomainDbContext>());
    

    That way, you'll be able to inject both types, and both types will actually be the same instance, which you can easily check using GetHashCode or similar.