应直接使用Npgsql而非ODBC或旧版System.Data.Odbc;连接字符串必须显式指定sslmode=require(云环境)或disable(本地开发),且不可省略Port;查询须用参数化防止注入;读取大字段应流式处理,连接池默认开启不可关闭。

直接用 Npgsql,别碰 ODBC 或旧版 .NET Framework 的 System.Data.Odbc —— 它们要么性能差,要么在 .NET 6+ 上缺维护、连 sslmode=require 都可能静默失败。
安装和初始化 Npgsql 连接
从 NuGet 安装 Npgsql(不是 Npgsql.EntityFrameworkCore.PostgreSQL,那是 EF 专用包):
dotnet add package Npgsql
连接字符串必须显式声明 sslmode,否则在云数据库(如 AWS RDS、Supabase)上大概率报 28000: no pg_hba.conf entry 错误:
Host=localhost;Port=5432;Database=mydb;Username=usr;Password=pass;sslmode=require- 若本地开发且 PostgreSQL 未启用 SSL,改用
sslmode=disable,但上线前必须切回require - 不要省略
Port:默认是 5432,但 Docker 或某些托管服务会映射到其他端口,不写就连不上
执行查询时防 SQL 注入的唯一正确方式
NpgsqlCommand 支持位置参数(@name),但 PostgreSQL 原生用的是 , 占位符 —— Npgsql 自动做了映射,所以两种写法都行,但必须用参数化:
using var cmd = new NpgsqlCommand("SELECT * FROM users WHERE email = @email AND status = @status", conn);
cmd.Parameters.AddWithValue("@email", "a@b.com");
cmd.Parameters.AddWithValue("@status", "active");常见错误:
- 拼接字符串:
"WHERE email = '" + email + "'"→ 直接被注入 - 用
string.Format或插值:$"WHERE email = '{email}'"→ 同样危险 - 参数名大小写不一致:
@Email和@email被视为不同参数,查不到数据也不报错
读取大字段(JSON、BYTEA)或流式响应的注意事项
PostgreSQL 的 jsonb 字段在 C# 中默认读成 string,不是 JObject 或 JsonDocument;bytea 默认是 byte[],但大文件(> 1MB)建议流式读取,避免内存暴涨:
- 读
jsonb:用cmd.ExecuteScalar()得到string,再用System.Text.Json.JsonSerializer.Deserialize<t>()</t> - 读
bytea大对象:调用cmd.ExecuteReader()后,用reader.GetStream(0)获取Stream,而非reader.GetValue(0) - 别在
using块外访问NpgsqlDataReader—— 它依赖活跃的连接,提前释放连接会导致InvalidOperationException: The connection was closed
最常被跳过的细节:连接字符串里漏掉 sslmode,或者把 Pooling=true(默认开启)当成可有可无的配置 —— 关闭连接池后,高频请求下会迅速耗尽 socket,表现为随机超时或 Unable to connect to any of the specified PostgreSQL hosts。真正要调优的是 Max Pool Size 和 Timeout,不是关池子。


















