I'm building ASP.Net app which is a simulator, lots of action will happens outside of Controller as separate threat, but I'm struggling to create DbContext connection outside of Controller. I know I could use OnConfiguring(DbContextOptionsBuilder optionsBuilder) but it doesn't look to my as most elegant way to do it.
I through something like this should work:
public class SimRepository : ISimRepository
{
public IConfiguration _configuration;
public DbContextOptionsBuilder _dbOptions;
public SimRepository(IConfiguration configuration)
{
_configuration = configuration;
_dbOptions = new DbContextOptionsBuilder();
_dbOptions.UseSqlServer(_configuration.GetConnectionString("DefaultConnection"));
}
public void LatheIn()
{
using (AppDbContext db = new AppDbContext(_dbOptions.Options))
{
}
}
}
but I receive this error:
Argument 1: cannot convert from Microsoft.EntityFrameworkCore.DbContextOptions' to Microsoft.EntityFrameworkCore.DbContextOptions<Simulator_Line.Server.AppDbContext>
In Startup:
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddMvc();
//Enable use of appsettings.json outside of Startup.cs
services.AddSingleton(Configuration);
services.AddSingleton<IConfiguration>(Configuration);
}
If my approach is incorrect, I'm open to for changes.
EDIT
public class LatheController : Controller
{
private readonly AppDbContext _dbContext;
private readonly SimRepository _simRrepo;
public LatheController(AppDbContext dbContext, SimRepository latheRepo)
{
_dbContext = dbContext;
_simRrepo = latheRepo;
}
[HttpGet]
public IEnumerable<Lathe> GetLathes()
{
_simRrepo.LatheIn();
return _dbContext.Lathes;
}
}
You have already registered the DbContext in the service collection. Just inject it into the dependent class so that it can be resolved when the dependent class is being resolved
public class SimRepository : ISimRepository {
public readonly AppDbContext db;
public SimRepository(AppDbContext db) {
this.db = db;
}
public void LatheIn() {
//...use db
}
}
You can create a factory
public interface IAppDbContextFactory {
AppDbContext Create();
}
Which be used for creating instances as needed
public class SimRepository : ISimRepository {
public readonly IAppDbContextFactory factory;
public SimRepository(IAppDbContextFactory factory) {
this.factory = factory;
}
public void LatheIn() {
using (AppDbContext db = factory.Create()) {
//...use db
}
}
}
Factory implementation could look like
public class AppDbContextFactory : IAppDbContextFactory {
private readonly IServiceProvider servideProvider;
public AppDbContextFactory(IServiceProvider servideProvider) {
this.serviceProvider = serviceProvider;
}
public AppDbContext Create() {
return serviceProvider.GetService<AppDbContext>();
}
}
Make sure to register the your types with the service collection.
public void ConfigureServices(IServiceCollection services) {
// Add framework services.
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddMvc();
//Enable use of appsettings.json outside of Startup.cs
services.AddSingleton(Configuration);
services.AddSingleton<IConfiguration>(Configuration);
services.AddSingleton<IAppDbContextFactory, AppDbContextFactory>();
services.AddTransient<ISimRepository, SimRepository>();
}
So that it can be used where needed
public class SomeController : Controller {
private readonly ISimRepository simRepository;
public SomeController(ISimRepository simRepository) {
this.simRepository = simRepository;
}
public IActionResult SomeAction() {
simRepository.LatheIn();
return Ok();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With