简体   繁体   中英

Create two EF contexts for the same model

I have an app that interacts with two MySQL databases, one of which is a replica. When I need to perform transactions, I use the master db, when I need to access some historical data or perform some costlier selects I use the slave db.

I tried the following:

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

    public DbSet<Order> Orders { get; set; }
    public DbSet<Customer> Customers { get; set; }
    //...

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.EnableSensitiveDataLogging();
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        //...
    }
}

public class MyMainDbContext : MyDbContext
{
    public MyMainDbContext(DbContextOptions<MyDbContext> options) : base(options)
    {
    }
}

public class MyReplicationDbContext : MyDbContext
{
    public MyReplicationDbContext(DbContextOptions<MyDbContext> options) : base(options)
    {
    }
}

In Startup.cs I have the following services configured:

public void ConfigureServices(IServiceCollection services)
{
        services.AddDbContext<MyMainDbContext>(options =>
            options.UseMySql(Configuration.GetConnectionString("DefaultConnection")));

        services.AddDbContext<MyReplicationDbContext>(options =>
            options.UseMySql(Configuration.GetConnectionString("ReplicationConnection")));

        services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<MyMainDbContext>()
            .AddDefaultTokenProviders();

        services.Configure<IdentityOptions>(options =>
        {
            // Password settings
        });
        //...
}

And I would use these two contexts like so:

public class StockController : Controller
{
    private readonly MyMainDbContext _context;

    public StockController(MyMainDbContext context)
    {
        _context = context;
    }
    
    public async Task<IActionResult> Index()
    {
        //I only need MyMainDbContext here
    }
    
    public async Task<IActionResult> LastMonthsAverageStock([FromServices] MyReplicationDbContext replicationContext)
    {
        //I need MyReplicationDbContext here, it's an expensive query and fresh data is not important
    }
}

I'm getting the following exception:

InvalidOperationException: Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContextOptions`1[StockApp.DataModels.MyDbContext]' while attempting to activate 'StockApp.DataModels.MyMainDbContext'.

My question: is this the right way to go about this? What am I missing?

you have to create 2 constructors:

public class MyDbContext : IdentityDbContext<ApplicationUser>
{
 public MyDbContext()
 {
 }
    public MyDbContext(DbContextOptions<MyMainDbContext> options) : base(options)
    {
    }

   public MyDbContext(DbContextOptions<MyReplicationDbContext> options) : base(options)
    {
    }
   
}

public class MyMainDbContext : MyDbContext
{
    public MyMainDbContext(DbContextOptions<MyMainDbContext> options) : base(options)
    {
    }
}

public class MyReplicationDbContext : MyDbContext
{
    public MyReplicationDbContext(DbContextOptions<MyReplicationDbContext> options) : base(options)
    {
    }
}

Startup:

services.AddDbContext<MyMainDbContext>(options => options.MySql(Configuration.GetConnectionString("DefaultConnection")));

services.AddDbContext<MyReplicationDbContext>(options => options.MySql(Configuration.GetConnectionString("ReplicationConnection")));

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