简体   繁体   中英

Registering multiple DBContexts in .net core with same base class

So just curiosity here, I have an app that has an internal site and an external site. The db for them is identical. Basically the internal app is for users to change data that is shown on the external app. So for this, I decided to create a single db context for the app for the internal db connection. I then created another context that inherited from the internal one for the external connection I did this because I thought I could add them to the service and set each up to it's own database. When I inject them into my promoter class, both db connections are pointing to the same db. Why is this? So what I have for my contexts is:

public class AppContext : DbContext
{
    public AppContext() { }

    public AppContext(DbContextOptions<AppContext> options): base(options)
    { }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Folder.Folder>().ToTable("Folders");

        modelBuilder.Entity<File.File>().ToTable("Files");

        modelBuilder.Entity<DocumentView>().ToTable("DocumentViews")
            .HasKey(c=> new { c.PersonId, c.DocId });

        modelBuilder.Entity<AppInfo>().ToTable("AppInfo");
    }

    public DbSet<Folder.Folder> Folders { get; set; }
    public DbSet<File.File> Files { get; set; }
    public DbSet<DocumentView> DocumentViews { get; set; }
    public DbSet<AppInfo> AppInfos { get; set; }
}

public class ExternalAppContext : AppContext
{
    public ExternalAppContext(DbContextOptions<AppContext> options) : base(options)
    { }
}

When I registered them in my startup, I registered them as such.

services.AddDbContext<AppContext>(options => options.UseSqlite(@"Data Source=" + Configuration["SqlConnection:adminDbLocation"]));
services.AddDbContext<ExternalAppContext>(options => options.UseSqlite(@"Data Source=" + Configuration["SqlConnection:externalDbLocation"]))

Promoter class injection is:

public Promoter(ExternalAppContext externalContext, AppContext adminContext)
{
    _externalContext = externalContext;
    _adminContext = adminContext;
}

So the real answer here was nested in a github answer from three years ago that can be found https://github.com/dotnet/efcore/issues/7533 . The issue comes down to how the services are being rendered for pooling, which is why when registering multiple DbContexts that you have to specify the type on the DbContextOptions. To get around this on the base class you can have a protected constructor for the options. This will allow the pooling to work correctly and allow you to inherit the context. The example given by greggbjensen on Dec 2017 is below and was exactly what I was looking for.

public class MainDbContext : DbContext
{
    public MainDbContext(DbContextOptions<MainDbContext> options)
        : base(options)
    {
    }

    protected MainDbContext(DbContextOptions options)
        : base(options)
    {
    }
}

public class SubDbContext : MainDbContext
{
    public SubDbContext (DbContextOptions<SubDbContext> options)
        : base(options)
    {
    }
}

This allows for two services to be set up in the .net core services code as such.

services.AddDbContext<MainDbContext >(options => [[SomeOptionsHere]]);
services.AddDbContext<SubDbContext >(options => [[SomeOptionsHere]]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM