排坑日记:SqlSugar 连接 PostgreSQL 报错 42P01: relation does not exist 的排查与修复

简介: 项目调用药品接口时因 PostgreSQL 表名大小写不匹配报错 `42P01: relation "drugs" does not exist`。根本原因是 SqlSugar 未配置 `PgSqlIsAutoToLower = true`,导致生成的 SQL 使用小写 `"drugs"` 查询,而实体标注为 `"Drugs"`,与数据库默认小写表名不一致。修复需在 `ConnectionConfig.MoreSettings` 中启用三项自动转小写配置,使 ORM 与 PostgreSQL 标识符规则对齐。

一、问题现象

在项目中调用 GET /api/drugs?drugId=xxx 接口时,服务端抛出 500 异常,日志关键信息如下:

2026-06-15 17:09:37.599 +08:00 [ERR] An unhandled exception has occurred while executing the request.
Npgsql.PostgresException (0x80004005): 42P01: relation "drugs" does not exist
   at SqlSugar.QueryableProvider`1.FirstAsync()
   at ...Services.DrugService.GetDrugByIdAsync(String drugId)
   at ...Controllers.DrugController.GetDrugByIdAsync(String drugId)

报错代码 42P01 在 PostgreSQL 中代表「关系不存在」,通常是指查询中引用的表(或视图)在当前数据库内找不到。

二、从 SQL 日志中找线索

打开 Program.cs 查看 SqlSugar 注册代码,注意到配置了 Aop.OnLogExecuting 事件,所以日志中完整输出了生成的 SQL:

SQL: SELECT "id","name","normalizedname",... FROM "drugs" WHERE ( "id" = @Id0 ) LIMIT 1 offset 0

与此同时,Drugs 实体类定义在 MyCommon/Entities/Drugs.cs 中:

[SugarTable("Drugs")]
public partial class Drugs
{
   
    [SugarColumn(IsPrimaryKey = true)]
    public string Id {
    get; set; } = null!;
    public string Name {
    get; set; } = null!;
    // ...
}

把上面两段信息放在一起,问题就浮出水面了:

代码中的名称 SQL 中实际出现的名称
Drugs(类名 + SugarTable) "drugs"(双引号包裹,全小写)
Id(属性名) "id"(双引号包裹,全小写)
Name(属性名) "name"(双引号包裹,全小写)

SqlSugar 生成的表名和列名与实体类中定义的完全对不上——这就是 42P01 的直接原因。

三、PostgreSQL 的大小写敏感规则

在继续分析之前,必须先明确一条 PostgreSQL 的核心行为规则:

不加双引号的标识符会被自动折叠为小写,因此大小写不敏感;加上双引号 "Name" 包裹的标识符会严格区分大小写。

举例来说:

CREATE TABLE Drugs (...);    -- 实际存进系统表的是 drugs(小写)
CREATE TABLE "Drugs" (...);  -- 实际存进系统表的是 Drugs(保留大写)

SELECT * FROM Drugs;         -- 等价于 SELECT * FROM drugs; 能命中
SELECT * FROM "Drugs";       -- 只能命中保留大写的表 "Drugs"
SELECT * FROM "drugs";       -- 只能命中保留小写的表 "drugs"

Drugs 实体标注了 [SugarTable("Drugs")],说明期望查询的表叫 Drugs;但 SqlSugar 实际生成的 SQL 却变成了 "drugs"。如果数据库中的表名是按 PostgreSQL 默认行为建的(即小写 drugs),理论上应该命中;如果按保留大写建的("Drugs"),那就匹配不上。

无论数据库中的表是哪一种,让 SqlSugar 按 PostgreSQL 的默认小写规则去生成 SQL,是兼容性最好的做法。而控制 SqlSugar 这一行为的开关,正是 ConnMoreSettings 中的 PgSqlIsAutoToLower

四、真正的根因:缺少 ConnMoreSettings 配置

回到项目中 Program.cs,最初注册 SqlSugar 的代码是这样的(修改前):

builder.Services.AddScoped<ISqlSugarClient>(options =>
{
   
    ISqlSugarClient sugarClient = new SqlSugarClient(new ConnectionConfig()
    {
   
        ConnectionString = configuration.GetConnectionString("DefaultConnection"),
        DbType = DbType.PostgreSQL,
        IsAutoCloseConnection = true,
        // ← 这里没有配置 ConnMoreSettings
    }, db => {
    db.Aop.OnLogExecuting = (sql, pars) => {
    Log.Information($"SQL: {sql} {pars}"); }; });
    return sugarClient;
});

没有配置 MoreSettings,意味着 SqlSugar 对 PostgreSQL 的大小写处理使用其内部默认逻辑,生成的表名/列名与数据库中实际的表名列名不匹配,于是报 42P01

注意:我在第一次排查时曾误以为代码里已有 PgSqlIsAutoToLower = false,后经指正才明确——原始代码里根本没有这段配置PgSqlIsAutoToLower = false 是用户后来手动加上的「尝试性修复」,但它同样不对(显式禁止小写转换依然无法匹配数据库中的小写表名)。

五、修复方案

ConnectionConfig 中添加 MoreSettings,并将三个 PgSql*ToLower 开关设为 true

builder.Services.AddScoped<ISqlSugarClient>(options =>
{
   
    ISqlSugarClient sugarClient = new SqlSugarClient(new ConnectionConfig()
    {
   
        ConnectionString = configuration.GetConnectionString("DefaultConnection"),
        DbType = DbType.PostgreSQL,
        IsAutoCloseConnection = true,
        MoreSettings = new ConnMoreSettings()
        {
   
            PgSqlIsAutoToLower = true,
            PgSqlIsAutoToLowerSchema = true,
            PgSqlIsAutoToLowerCodeFirst = true,
        }
    }, db => {
    db.Aop.OnLogExecuting = (sql, pars) => {
    Log.Information($"SQL: {sql} {pars}"); }; });
    return sugarClient;
});

三个开关的作用:

配置项 作用
PgSqlIsAutoToLower 普通查询时,是否将表名、列名自动转为小写
PgSqlIsAutoToLowerSchema 模式(Schema)名是否自动转小写
PgSqlIsAutoToLowerCodeFirst Code First 建表/迁移时是否使用小写

设置为 true 后,SqlSugar 会把 [SugarTable("Drugs")] 处理成 "drugs",把 IdName 等属性处理成 "id""name",与 PostgreSQL 中默认小写的标识符规则完全对齐。

六、验证步骤

  1. 重新编译dotnet build,确认无编译错误
  2. 重启服务:运行项目
  3. 观察启动日志:确认启动信息和连接字符串正常输出
  4. 调用接口GET /api/drugs?drugId=xxx
  5. 核对 SQL 日志:期望看到 FROM "drugs"(全小写),不再有 42P01
  6. 接口返回:能正确返回 Drugs 对象或 null

七、经验总结

这次排查的关键收获有三点:

1. PostgreSQL 的「双引号陷阱」必须牢记。 不加引号时大小写不敏感,加了引号就严格区分大小写。在团队协作中,建议统一采用「建表不加双引号,SQL 中也不要手写双引号」的约定,从源头避免此类问题。

2. SqlSugar 连接 PostgreSQL 必须显式配置 ConnMoreSettings 尤其是 PgSqlIsAutoToLower 这个开关,它直接决定了 ORM 层面与数据库层面标识符能否对上。缺失这段配置是比写 = false 更隐蔽的坑——因为看起来好像什么都没做错。

3. 善用 ORM 的 SQL 日志输出。 SqlSugar 的 OnLogExecuting 是排查这类问题的最直接工具。如果看不到实际生成的 SQL,你可能永远猜不到是大小写在作怪。养成在开发环境开启 SQL 日志的习惯,能帮你省下大量定位时间。

目录
相关文章
|
2月前
|
开发框架 关系型数据库 .NET
asp.net core webapi接入SqlSugar操作PostgreSQL:从零到一完整实战
本文详解 ASP.NET Core WebAPI 项目中,基于 SqlSugarCore 5.1.4.214 快速集成 PostgreSQL(12+)的完整实践:涵盖环境搭建、连接配置、自动建表、异步 CRUD 及分页接口,适配 .NET 6/7/8,Rider 开发,开箱即用。
180 1
asp.net core webapi接入SqlSugar操作PostgreSQL:从零到一完整实战
|
4月前
|
人工智能 缓存 Serverless
Serverless 架构下 AI Agent 工程化落地的几个关键点
本文探讨Serverless架构如何破解AI Agent落地难题:通过弹性GPU算力降本33%、NAS实现有状态运行、A2A协议支持多Agent协同,并提供开箱即用的场景化模板,助力企业从Demo快速迈向生产。
|
2月前
|
消息中间件 Linux Docker
Windows Docker Desktop 环境下 RabbitMQ 生产级部署完整指南
本文详解Windows下基于Docker Desktop部署RabbitMQ的标准化方案:避开Erlang配置痛点,推荐`rabbitmq:3.13-management-alpine`镜像;涵盖极简测试、持久化部署(必设`--hostname`)、自定义配置三类方案,并重点梳理Windows特有坑点(BOM编码、CRLF换行、guest远程限制等),助力快速搭建稳定本地开发环境。
336 7
|
负载均衡 前端开发 算法
如何使用Nginx 部署前端项目,什么是反向代理?
Nginx可以作为静态web服务器来部署静态资源。这里所说的静态资源是指在我们web服务端真实存在,并且能够直接展示的一些文件,比如常见的html页面
如何使用Nginx 部署前端项目,什么是反向代理?
|
7月前
|
SQL 人工智能 自然语言处理
企业落地 AI 数据分析,如何做好敏感数据安全防护?
在 AI 问数时代,数据安全与使用效率并非零和博弈。
|
5月前
|
人工智能 监控 算法
AI英语App的分类
2026年AI英语App已升级为拟人化“数字私人教练”,深度融合ASR、LLM、TTS与多智能体技术。主流分为沉浸口语陪练、考试模拟、游戏化学习及自适应教练四类,依托语音-逻辑-语音闭环、RAG知识库与Agentic UI,实现音素级纠音、多口音切换与情境化交互。(239字)
|
负载均衡 安全 应用服务中间件
子域名怎么申请HTTPS证书?
在当今注重网络安全的时代,为子域名申请HTTPS证书(SSL证书)至关重要。首先选择合适的证书类型:单域名证书适合单一子域名;通配符证书适用于同一主域名下的多个子域名;多域名证书则可保护不同主域名下的子域名。接着选择可信的CA机构,如锐安信sslTrus、Sectigo、CFCA或DigiCert等。随后按照申请流程填写信息、生成CSR文件并提交,完成域名及企业信息验证后获取证书并正确安装。根据需求和预算选择最佳方案,提升网站安全性与用户信任度。
|
存储 机器学习/深度学习 算法
数据结构-树与二叉树
数据结构-树与二叉树
547 0
|
开发者
2024 乘风者计划全新启航!快来加入吧!
 2021年,阿里云开发者社区焕新升级,重磅推出“乘风者计划”!诚邀四海技术博主入驻社区,泼墨云间,书写天地。入驻社区,即可享丰厚权益! 新的一年,乘风者计划重磅升级!
252469 81
|
SQL XML 存储
Microsoft Access 是微软公司开发的关系型数据库管理系统(
【5月更文挑战第14天】Microsoft Access 是微软公司开发的关系型数据库管理系统(
679 1