Something that used to be relatively easy, isn't so anymore. Of the dozens of times I've searched, I rarely find an answer to this situation, which I cannot believe is anything other than prevalent in most project structures.
I have the standard Core 2.0 Web app, and for now, for simplicity sake, an Infrastructure project and a unit test project. I have a good idea how to accomplish the test scenario since the test project doesn't run asp.net and I have a great video tutorial on how to accomplish it.
The problem lies with getting access to the DbContext in my infrastructure project. (.Net Core class library)
The DbContext sets up perfectly fine in Startup
var connString = Configuration.GetSection("ApplicationConfiguration:ConnectionStrings:DefaultConnection").Value;
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connString));
And in a controller I can access it
private ApplicationDbContext _context;
private IConfiguration Configuration { get; set; }
public HomeController(IConfiguration configuration, ApplicationDbContext context)
{
_context = context;
Configuration = configuration;
}
public IActionResult Index()
{
// gets users from the DI injected context in the controller
var users = _context.AppUsers.ToList();
// if GetUsers is defined statically, this doesn't work because the injected context is always null
//var diUsers = DatabaseService.GetUsers():
// making it non-static and newing it up works, but defeats the purpose because you are passing the context, asp.net is not injecting it
var ds = new DatabaseService(_context);
var diUsers = ds.GetUsers();
var svm = SettingsViewModel();
return View(svm);
}
DatabaseService
private ApplicationDbContext _context;
//this is the constructor for DatabaseService class
public DatabaseService(ApplicationDbContext context)
{
_context = context;
}
public List<ApplicationUser> GetUsers()
{
var users = _context.AppUsers.ToList();
return users;
}
Yes, I know I should be using a repository and I will once I get this figured out correctly. How do I set up my classes in the Infrastructure project so I have the injected DbContext created at Startup and not have to pass it as a parameter.
Addendum:
Using the answer provided by Nkosi, I can inject the data service in the controller and use it.
But if I have a separate Infrastructure project (Asp.net core 2 class library), which implements my repository and UoW
public class GenericRepository<T> : IRepository<T> where T : class
{
public GenericRepository()
{
}
//rest of code removed
}
How can I get the DbContext injected there? Do I need to create an Interface, IDbContext, to wrap DbContext, and register that in startup?
Assuming you have the following for your service
public interface IDatabaseService {
List<ApplicationUser> GetUsers();
//...
}
public class DatabaseService : IDatabaseService {
public DatabaseService(ApplicationDbContext context) {
//...code removed for brevity
}
//...code removed for brevity
}
The service explicitly depends on the ApplicationDbContext
which will be injected when the implementation is being resolved from the service container.
Register the service in Startup.ConfigureServices
var connString = Configuration.GetSection("ApplicationConfiguration:ConnectionStrings:DefaultConnection").Value;
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connString));
services.AddScoped<IDatabaseService, DatabaseService>();
And refactor the controller to explicitly depend on the service
private IDatabaseService ds;
private IConfiguration Configuration { get; set; }
public HomeController(IConfiguration configuration, IDatabaseService ds) {
this.ds = ds;
Configuration = configuration;
}
public IActionResult Index() {
var diUsers = ds.GetUsers();
var svm = SettingsViewModel();
return View(svm);
}
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