Refactor database connection handling and update environment variable usage across Docker configurations

This commit is contained in:
Aaron Po
2026-02-08 14:57:45 -05:00
parent b22e1e5702
commit 243931eb6a
13 changed files with 234 additions and 45 deletions

View File

@@ -16,4 +16,4 @@ WORKDIR /src
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
RUN mkdir -p /app/test-results
WORKDIR /src/API/API.Specs
ENTRYPOINT ["dotnet", "test", "API.Specs.csproj", "-c", "Release", "--no-build", "--no-restore", "--logger", "trx;LogFileName=/app/test-results/test-results.trx"]
ENTRYPOINT ["dotnet", "test", "API.Specs.csproj", "-c", "Release", "--logger", "trx;LogFileName=/app/test-results/test-results.trx"]

View File

@@ -10,11 +10,6 @@ namespace API.Specs
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.UseEnvironment("Testing");
builder.ConfigureAppConfiguration((context, configBuilder) =>
{
var connectionString = Environment.GetEnvironmentVariable("DB_CONNECTION_STRING");
});
}
}
}

View File

@@ -7,8 +7,39 @@ namespace Database.Migrations;
public static class Program
{
private static readonly string? connectionString = Environment.GetEnvironmentVariable("DB_CONNECTION_STRING");
private static readonly string? masterConnectionString = Environment.GetEnvironmentVariable("MASTER_DB_CONNECTION_STRING");
private static string BuildConnectionString(string? databaseName = null)
{
var server = Environment.GetEnvironmentVariable("DB_SERVER")
?? throw new InvalidOperationException("DB_SERVER environment variable is not set");
var dbName = databaseName
?? Environment.GetEnvironmentVariable("DB_NAME")
?? throw new InvalidOperationException("DB_NAME environment variable is not set");
var user = Environment.GetEnvironmentVariable("DB_USER")
?? throw new InvalidOperationException("DB_USER environment variable is not set");
var password = Environment.GetEnvironmentVariable("DB_PASSWORD")
?? throw new InvalidOperationException("DB_PASSWORD environment variable is not set");
var trustServerCertificate = Environment.GetEnvironmentVariable("DB_TRUST_SERVER_CERTIFICATE")
?? "True";
var builder = new SqlConnectionStringBuilder
{
DataSource = server,
InitialCatalog = dbName,
UserID = user,
Password = password,
TrustServerCertificate = bool.Parse(trustServerCertificate),
Encrypt = true
};
return builder.ConnectionString;
}
private static readonly string connectionString = BuildConnectionString();
private static readonly string masterConnectionString = BuildConnectionString("master");
private static bool DeployMigrations()
{

View File

@@ -3,9 +3,39 @@ using Microsoft.Data.SqlClient;
using DbUp;
using System.Reflection;
string BuildConnectionString()
{
var server = Environment.GetEnvironmentVariable("DB_SERVER")
?? throw new InvalidOperationException("DB_SERVER environment variable is not set");
var dbName = Environment.GetEnvironmentVariable("DB_NAME")
?? throw new InvalidOperationException("DB_NAME environment variable is not set");
var user = Environment.GetEnvironmentVariable("DB_USER")
?? throw new InvalidOperationException("DB_USER environment variable is not set");
var password = Environment.GetEnvironmentVariable("DB_PASSWORD")
?? throw new InvalidOperationException("DB_PASSWORD environment variable is not set");
var trustServerCertificate = Environment.GetEnvironmentVariable("DB_TRUST_SERVER_CERTIFICATE")
?? "True";
var builder = new SqlConnectionStringBuilder
{
DataSource = server,
InitialCatalog = dbName,
UserID = user,
Password = password,
TrustServerCertificate = bool.Parse(trustServerCertificate),
Encrypt = true
};
return builder.ConnectionString;
}
try
{
var connectionString = Environment.GetEnvironmentVariable("DB_CONNECTION_STRING");
var connectionString = BuildConnectionString();
Console.WriteLine("Attempting to connect to database...");

View File

@@ -7,11 +7,36 @@ namespace DataAccessLayer.Sql
{
public class DefaultSqlConnectionFactory(IConfiguration configuration) : ISqlConnectionFactory
{
private readonly string _connectionString = Environment.GetEnvironmentVariable("DB_CONNECTION_STRING")
?? configuration.GetConnectionString("Default")
?? throw new InvalidOperationException(
"Database connection string not configured. Set DB_CONNECTION_STRING env var or ConnectionStrings:Default."
);
private readonly string _connectionString = GetConnectionString(configuration);
private static string GetConnectionString(IConfiguration configuration)
{
// Check for full connection string first
var fullConnectionString = Environment.GetEnvironmentVariable("DB_CONNECTION_STRING");
if (!string.IsNullOrEmpty(fullConnectionString))
{
return fullConnectionString;
}
// Try to build from individual environment variables (preferred method for Docker)
try
{
return SqlConnectionStringHelper.BuildConnectionString();
}
catch (InvalidOperationException)
{
// Fall back to configuration-based connection string if env vars are not set
var connString = configuration.GetConnectionString("Default");
if (!string.IsNullOrEmpty(connString))
{
return connString;
}
throw new InvalidOperationException(
"Database connection string not configured. Set DB_CONNECTION_STRING or DB_SERVER, DB_NAME, DB_USER, DB_PASSWORD env vars or ConnectionStrings:Default."
);
}
}
public DbConnection CreateConnection()
{

View File

@@ -0,0 +1,50 @@
using Microsoft.Data.SqlClient;
namespace DataAccessLayer.Sql
{
public static class SqlConnectionStringHelper
{
/// <summary>
/// Builds a SQL Server connection string from environment variables.
/// Expects DB_SERVER, DB_NAME, DB_USER, DB_PASSWORD, and DB_TRUST_SERVER_CERTIFICATE.
/// </summary>
/// <param name="databaseName">Optional override for the database name. If null, uses DB_NAME env var.</param>
/// <returns>A properly formatted SQL Server connection string.</returns>
public static string BuildConnectionString(string? databaseName = null)
{
var server = Environment.GetEnvironmentVariable("DB_SERVER")
?? throw new InvalidOperationException("DB_SERVER environment variable is not set");
var dbName = databaseName
?? Environment.GetEnvironmentVariable("DB_NAME")
?? throw new InvalidOperationException("DB_NAME environment variable is not set");
var user = Environment.GetEnvironmentVariable("DB_USER")
?? throw new InvalidOperationException("DB_USER environment variable is not set");
var password = Environment.GetEnvironmentVariable("DB_PASSWORD")
?? throw new InvalidOperationException("DB_PASSWORD environment variable is not set");
var builder = new SqlConnectionStringBuilder
{
DataSource = server,
InitialCatalog = dbName,
UserID = user,
Password = password,
TrustServerCertificate = true,
Encrypt = true
};
return builder.ConnectionString;
}
/// <summary>
/// Builds a connection string to the master database using environment variables.
/// </summary>
/// <returns>A connection string for the master database.</returns>
public static string BuildMasterConnectionString()
{
return BuildConnectionString("master");
}
}
}

View File

@@ -11,4 +11,4 @@ RUN dotnet build "./Repository.Tests.csproj" -c $BUILD_CONFIGURATION -o /app/bui
FROM build AS final
RUN mkdir -p /app/test-results
WORKDIR /src/Repository/Repository.Tests
ENTRYPOINT ["dotnet", "test", "./Repository.Tests.csproj", "-c", "Release", "--no-build", "--logger", "trx;LogFileName=/app/test-results/repository-tests.trx"]
ENTRYPOINT ["dotnet", "test", "./Repository.Tests.csproj", "-c", "Release", "--logger", "trx;LogFileName=/app/test-results/repository-tests.trx"]