npgsql ef core是entity framework core的postgresql数据提供程序,需区分纯npgsql驱动与ef core扩展包:仅ado.net手动执行sql时装npgsql;使用dbcontext和linq时才装npgsql.entityframeworkcore.postgresql(自动依赖npgsql)。

别装错包,EF Core 和纯 Npgsql 是两套东西;连不上八成是连接字符串漏了 sslmode 或 Port,不是代码写错了。
装包必须分清 Npgsql 和 Npgsql.EntityFrameworkCore.PostgreSQL
新手常在 NuGet 搜 “postgres” 顺手装了 Npgsql.EntityFrameworkCore.PostgreSQL,结果 NpgsqlConnection 类型找不到——因为这个包只提供 EF Core 的扩展,不带底层驱动。
- 只做 ADO.NET 手动 SQL 执行:只装
Npgsql - 要用
DbContext+ LINQ:装Npgsql.EntityFrameworkCore.PostgreSQL(它会自动拉取Npgsql作为依赖) - 用
dotnet add package Npgsql默认装最新版,但 .NET Framework 4.6.1 只能用Npgsql 3.2.7;否则运行时报Could not load file or assembly 'Npgsql, Version=8.0.0.0'
连接字符串里 sslmode 和 Port 不是可选项
云环境(Azure、AWS RDS、Supabase)默认强制 SSL,但 Npgsql 不设 sslmode 时默认行为是 prefer,结果报 28000: no pg_hba.conf entry 这种误导性错误。
- 云服务必须显式写
sslmode=require - 本地开发且 PostgreSQL 没开 SSL:用
sslmode=disable,但上线前务必改回 -
Port别省略:Docker 映射、Azure Flexible Server 常用非标端口(如6432),不写就直连失败 - 必须加
Timeout=30,否则卡住 15 秒才抛异常 - 正确示例:
Host=mydb.postgres.azure.com;Port=5432;Database=appdb;Username=appuser@mydb;Password=xxx;sslmode=require;Timeout=30
NpgsqlCommand 参数名必须用 :name,大小写敏感且不能用 @
PostgreSQL 原生用 :name 占位符,Npgsql 虽兼容 @name 写法,但底层只认 :name 绑定。写成 @id 看似不报错,实际参数值全为 NULL。
- SQL 中写
:email,代码里也必须用":email"(注意引号和冒号) -
:Email≠:email,不匹配也不报错,查不到数据 - 传
null时别用AddWithValue,它可能推断成int导致Can't write CLR type System.DBNull;改用cmd.Parameters.Add(":age", NpgsqlDbType.Integer).Value = DBNull.Value - 批量插入别拼字符串,用
UNNEST:INSERT INTO logs (msg, ts) SELECT * FROM UNNEST(:msgs, :tss),然后传两个string[]参数
读大字段(jsonb、bytea)必须流式处理
jsonb 默认读成 string,bytea 默认转 byte[],但超过 1MB 就容易触发 OOM。流式才是正解。
- 读
jsonb:先ExecuteScalar()拿string,再用System.Text.Json.JsonSerializer.Deserialize<t>()</t>解析 - 读大
bytea:用reader.GetStream(0),不是reader.GetValue(0) -
NpgsqlDataReader必须在using块内用完,提前释放连接会导致InvalidOperationException: The connection was closed - 别手动关连接再读流——
CommandBehavior.CloseConnection已过时,DataReader依赖连接生命周期
最容易被忽略的是:连接池 Polling=true 不可关闭,设 false 会被忽略;高频请求下关掉它会导致连接数爆炸、TCP 耗尽、响应延迟陡增。











