Previous lesson: π§± Lesson 4β - Adding SQL Server Support (Multi-Database Setup)
π Introduction
PostgreSQL is a powerful open-source database widely used in enterprise and cloud systems.
In multi-tenant or SaaS environments, itβs common to support multiple database providers (e.g., MySQL, SQL Server, PostgreSQL) based on customer or deployment needs.
Our goal today:
π³ Pull and run PostgreSQL via Docker
βοΈ Add PostgreSQL support in EF Core
ποΈ Create PostgresDbContext and design-time factory
π§± Run migrations and verify setup
π³ Step 1. Pull PostgreSQL Docker Image and Run Container
Letβs start by running PostgreSQL locally inside Docker.
docker pull postgres
![1]()
Run container
docker run -d --name postgres -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=Admin123! -p 5432:5432 postgres:latest
![2]()
βοΈ Step 2. Update appsettings.json
Add a new connection string for PostgreSQL in your ECommerce.API project.
"PostgreSQL":"Host=localhost;Port=5432;Database=ECommerceDb;Username=postgres;Password=Admin123!",
Now your application can dynamically choose the provider by changing:
"DatabaseProvider": "PostgreSQL"
![3]()
π§± Step 3. Create PostgreSQL DbContext
Path : ECommerce.Infrastructure/Data/PostgresDbContext.cs
using Microsoft.EntityFrameworkCore;
namespace ECommerce.Infrastructure.Data;
public class PostgresDbContext : AppDbContext
{
public PostgresDbContext(DbContextOptions<PostgresDbContext> options)
: base(options)
{
}
}
![4]()
Install Package
dotnet add ECommerce.Infrastructure package Npgsql.EntityFrameworkCore.PostgreSQL --version 8.0.11
π§© Step 5. Add Design-Time Factory
EF Core CLI needs this factory for dotnet ef migrations when it canβt build the host automatically.
Create PostgresDbContextFactory
Path : ECommerce.Infrastructure/Data/PostgresDbContextFactory.cs
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
namespace ECommerce.Infrastructure.Data;
public class PostgresDbContextFactory : IDesignTimeDbContextFactory<PostgresDbContext>
{
public PostgresDbContext CreateDbContext(string[] args)
{
var basePath = Path.Combine(Directory.GetCurrentDirectory(), "../ECommerce.API");
var configuration = new ConfigurationBuilder()
.SetBasePath(basePath)
.AddJsonFile("appsettings.json", optional: false)
.AddJsonFile("appsettings.Development.json", optional: true)
.Build();
var connectionString = configuration.GetConnectionString("PostgreSQL");
var optionsBuilder = new DbContextOptionsBuilder<PostgresDbContext>();
optionsBuilder.UseNpgsql(connectionString);
return new PostgresDbContext(optionsBuilder.Options);
}
}
![5]()
Update Dependency Injection
Path : ECommerce.Infrastructure/DependencyInjection.cs
using ECommerce.Infrastructure.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace ECommerce.Infrastructure;
public static class DependencyInjection
{
public static IServiceCollection AddInfrastructure(
this IServiceCollection services,
IConfiguration configuration)
{
var provider = configuration["DatabaseProvider"] ?? "MySQL";
if (string.Equals(provider, "SqlServer", StringComparison.OrdinalIgnoreCase))
{
var conn = configuration.GetConnectionString("SqlServer");
services.AddDbContext<AppDbContext, SqlServerDbContext>(options =>
options.UseSqlServer(conn));
}
else if (string.Equals(provider, "MySQL", StringComparison.OrdinalIgnoreCase))
{
var conn = configuration.GetConnectionString("MySQL");
services.AddDbContext<AppDbContext, MySqlDbContext>(options =>
options.UseMySql(conn, ServerVersion.AutoDetect(conn)));
}
else if (string.Equals(provider, "PostgreSQL", StringComparison.OrdinalIgnoreCase))
{
var conn = configuration.GetConnectionString("PostgreSQL");
services.AddDbContext<AppDbContext, PostgresDbContext>(options =>
options.UseNpgsql(conn));
}
else
{
throw new InvalidOperationException($"Unsupported provider: {provider}");
}
return services;
}
}
![6]()
π§± Step 6. Create Migrations
Now you can generate a separate migration folder for PostgreSQL.
dotnet ef migrations add InitPostgres -p ECommerce.Infrastructure -s ECommerce.API --context PostgresDbContext --output-dir "Migrations/PostgreSQL"
dotnet ef database update -p ECommerce.Infrastructure -s ECommerce.API --context PostgresDbContext
![7]()
![8]()
![9]()
Let's Connect using PGAdmin
![10]()
![11]()
Final Test and Verify
![12]()
![13]()
![14]()
Next Lecture Preview
Lecture 6 : Redis Caching for Performance Optimization
Installing and configuring Redis; caching responses, queries, and improving API performance.