In this article, we will explore how to connect a Blazor (Server or WebAssembly) application with a PostgreSQL database using ADO.NET (Npgsql).
This approach is especially useful when:
You prefer Stored Procedures or Raw SQL
You want to avoid ORM overhead
You are building banking or enterprise-grade systems
๐งฑ Architecture Overview
Blazor UI
โ
Service Layer
โ
Repository (ADO.NET)
โ
PostgreSQL (Npgsql)
๐ ๏ธ Prerequisites
๐ฆ Install Npgsql
dotnet add package Npgsql
๐ Connection String Configuration
{
"ConnectionStrings": {
"PostgresDb": "Host=localhost;Port=5432;Database=bankdb;Username=postgres;Password=postgres"
}
}
๐ Model (Entity)
public class Customer
{
public int Id { get; set; }
public string CustomerName { get; set; }
public string AccountNo { get; set; }
public decimal Balance { get; set; }
}
๐ง Repository Layer using ADO.NET
using Npgsql;
using System.Data;
public class CustomerRepository
{
private readonly IConfiguration _configuration;
public CustomerRepository(IConfiguration configuration)
{
_configuration = configuration;
}
private NpgsqlConnection GetConnection()
{
return new NpgsqlConnection(
_configuration.GetConnectionString("PostgresDb"));
}
public List<Customer> GetAllCustomers()
{
var customers = new List<Customer>();
using var conn = GetConnection();
using var cmd = new NpgsqlCommand("SELECT * FROM customers", conn);
conn.Open();
using var reader = cmd.ExecuteReader();
while (reader.Read())
{
customers.Add(new Customer
{
Id = reader.GetInt32("id"),
CustomerName = reader.GetString("customer_name"),
AccountNo = reader.GetString("account_no"),
Balance = reader.GetDecimal("balance")
});
}
return customers;
}
}
โ Pure ADO.NET โ No EF Core โ High performance and predictable behavior
๐งช Stored Procedure Example (PostgreSQL)
CREATE OR REPLACE FUNCTION get_customer_by_id(p_id INT)
RETURNS TABLE (
id INT,
customer_name TEXT,
account_no TEXT,
balance NUMERIC
)
AS $$
BEGIN
RETURN QUERY
SELECT * FROM customers WHERE id = p_id;
END;
$$ LANGUAGE plpgsql;
๐ Calling Stored Procedures from ADO.NET
public Customer GetCustomerById(int id)
{
using var conn = GetConnection();
using var cmd = new NpgsqlCommand("get_customer_by_id", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("p_id", id);
conn.Open();
using var reader = cmd.ExecuteReader();
if (reader.Read())
{
return new Customer
{
Id = reader.GetInt32("id"),
CustomerName = reader.GetString("customer_name"),
AccountNo = reader.GetString("account_no"),
Balance = reader.GetDecimal("balance")
};
}
return null;
}
๐ Service Layer
public class CustomerService
{
private readonly CustomerRepository _repo;
public CustomerService(CustomerRepository repo)
{
_repo = repo;
}
public List<Customer> GetCustomers()
{
return _repo.GetAllCustomers();
}
}
๐ฅ๏ธ Blazor Component (UI)
@page "/customers"
@inject CustomerService customerService
<h3>Customer List</h3>
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Account</th>
<th>Balance</th>
</tr>
</thead>
<tbody>
@foreach (var c in customers)
{
<tr>
<td>@c.CustomerName</td>
<td>@c.AccountNo</td>
<td>@c.Balance</td>
</tr>
}
</tbody>
</table>
@code {
List<Customer> customers = new();
protected override void OnInitialized()
{
customers = customerService.GetCustomers();
}
}
๐งฉ Dependency Injection Configuration
builder.Services.AddScoped<CustomerRepository>();
builder.Services.AddScoped<CustomerService>();
โ
Why Use ADO.NET with Blazor?
โ Ideal for financial applications
โ Heavy stored procedure usage
โ Full control over SQL execution
โ No hidden ORM behavior
๐ Conclusion
Blazor + PostgreSQL + ADO.NET is a proven, enterprise-grade combination. If you want maximum control, performance, and predictability without relying on an ORM, this architecture is an excellent choice.