6

I am using repository pattern on EF Core and Autofac in a windows service.

I have a service that needs to connect with the some dozen databases which have the same schema (same dbcontext) but only different data. How can I achieve this in my service using Autofac? Belo

public class ReportRepository : IReportRepository
    {
        private readonly ReportDbContext dbContext;

        public ReportRepository(ReportDbContext dbContext)
        {
            this.dbContext = dbContext
        }

        public SomeModel GetData()
        {
            return dbContext.SalesData;
        }
    }

    public class ReportService : IReportService 
    {
        private readonly IReportRepository reportRepositoryEUServer;

        public ReportService(IReportRepository reportRepositoryEUServer)
        {
            this.reportRepositoryEUServer = reportRepositoryEUServer
        }

        public SomeModelDto GenerateReport()
        {
            var euData =  reportRepositoryEUServer.GetData();
            // I need to call other servers (e.g LATAM) here and get the data and aggregate them with euData
        }       
    }
pantonis
  • 5,601
  • 12
  • 58
  • 115
  • did you check Decorators in autofac documation https://autofaccn.readthedocs.io/en/latest/advanced/adapters-decorators.html – sonertbnc May 06 '19 at 12:46

1 Answers1

7

Create base context including all settings, dbsets etc:

public abstract class BaseContext : DbContext
{
    public BaseContext(DbContextOptions options)
    : base(options)
    { }
    public DbSet<object> FirstSet { get; set; }
    ...
}

inherit from BaseContext for both DBs

public class LATAMContext : BaseContext
{
    public LATAMContext(DbContextOptions<LATAMContext> options) : base(options)
    {

    }
}

public class EUContext : BaseContext
{
    public EUContext(DbContextOptions<EUContext> options) : base(options)
    {

    }
}

and register both in Startup.cs

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<LATAMContext>(options => options.UseSqlServer(Configuration.GetConnectionString("LATAMConnectionString")));
    services.AddDbContext<EUContext>(options => options.UseSqlServer(Configuration.GetConnectionString("EUConnectionString")));

    // Autofac
    var builder = new ContainerBuilder();

    // needed only if you plan to inject ICollection<BaseContext>
    builder.RegisterType<LATAMContext>().As<BaseContext>();
    builder.RegisterType<EUContext>().As<BaseContext>();

    builder.Populate(services);


    return new AutofacServiceProvider(builder.Build());
}

add connection strings in appsettings.json

"ConnectionStrings": {
  "LATAMConnectionString": "Server=(localdb)\\mssqllocaldb;Database=ContosoUniversity1;Trusted_Connection=True;MultipleActiveResultSets=true",
  "EUConnectionString": "Server=(localdb)\\mssqllocaldb;Database=ContosoUniversity1;Trusted_Connection=True;MultipleActiveResultSets=true"
}

and now you can inject both contexts

public class ReportRepository : IReportRepository
{
    private readonly LATAMContext latamDbContext;
    private readonly EUContext euDbContext;

    public ReportRepository(LATAMContext latamDbContext, EUContext euDbContext)
    {
        this.latamDbContext = latamDbContext;
        this.euDbContext = euDbContext;
    }
}

or if you plan to inject collection of contexts

public class ReportRepository : IReportRepository
{
    private readonly ICollection<BaseContext> dbContexts;

    public ReportRepository(ICollection<BaseContext> dbContexts)
    {
        this.dbContexts = dbContexts;
    }
}

to access specific context

var _euContext = dbContexts.FirstOrDefault(x => x is EUContext) as EUContext;
var _latamContext = dbContexts.FirstOrDefault(x => x is LATAMContext) as LATAMContext;
Greg
  • 346
  • 1
  • 10
  • Your solution seems ok but it is not what I want. I just gave a sample of two connections. I have dozens of these and hardcoding them is gonna be a mess. I will update the question as it was my mistake initially to not mention this. – pantonis May 04 '19 at 05:03
  • check it: https://stackoverflow.com/questions/40836102/asp-net-core-change-ef-connection-string-when-user-logs-in should fit your needs – Greg May 04 '19 at 10:17
  • @Greg Does this work well with Code First Entity Framework DB Migrations? – Mbuso Mkhize Jan 07 '20 at 09:03
  • @MbusoMkhize you can specify which context to use for migration ```--context MyDbContext``` – Greg Jul 20 '20 at 22:25