Dependency Injection definitely has it's advantages. However there are some benefits to not us it.
However for my person WebAPI, I chose to skip DI for my DB connections, and instead generate my Entity Framework (EF) classes, and simply use them in my middle layer. All Unit Tests will actually be full integration tests, testing calls fully to the database.
As a result, I just wanted to pull the connection string from the appsettings.json, and invoke my EF as typically done:
using (QuidDbContext context = GetQuidContext())
This code needed to work in both my WebAPI and my Unit Test projects. Both pulling the connection string from the app settings.
Goals summary
To summarize my goals, I wanted to:
- Not use DI, but just invoke my DB context were I need it
- Have the DB context pull its connection string from the appsettings.json
- Build my EF classes via scaffolding, and not have any custom code be lost each time I refreshed via scaffolding.
My simple EF Connection String solution
The solution was rather simple:
- Create the EF model, with the context simply called
QuidBaseContext
. - Create a version that inherits from it called
QuidDbContext
. - In that, have it store the connection string locally (private string), have the constructor either take that value, or look it up from the app settings.
- In that class, also override
OnConfiguring
to use this connection string
Here is that class in its entirety:
public class QuidDbContext : QuidBaseContext { private string _connectionString = string.Empty; /// <summary> /// Default constructor: Gets the "QuidDB" connection string from Configuration /// </summary> public QuidDbContext() { IConfigurationBuilder builder = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true); var config = builder.Build(); _connectionString = config.GetConnectionString("QuidDB"); } /// <summary> /// Constructor that takes a connection string /// </summary> /// <param name="connectionString"></param> public QuidDbContext(string connectionString) { _connectionString = connectionString; } /// <summary> /// Provided here for injection usage (which I'm currently not using) /// </summary> /// <param name="options"></param> public QuidDbContext(DbContextOptions<QuidContext> options) : base(options) { } /// <summary> /// Override this to use our _connectionString /// </summary> /// <param name="optionsBuilder"></param> protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { if (!optionsBuilder.IsConfigured) { if (!string.IsNullOrEmpty(_connectionString)) { optionsBuilder.UseSqlServer(_connectionString); } else { optionsBuilder.UseSqlServer("Server=localhost;Database=Quid_Dev;Trusted_Connection=True;"); } } } }
Add references!
BTW, to get this to work you (as of .NET Core 5), you need to add references to:
- Microsoft.Extensions.Configuration.FileExtensions
- Microsoft.Extensions.Configuration.Json
Simplified Unit Tests
Using this technique simplified my Unit Tests. I simply created a MSTest project, referenced my WebAPI, added the connection string to my appsettings.json (pointing to Dev), and started writing integration tests.