PostgreSQL 触发器和通知功能未按预期工作

问题描述 投票:0回答:1

问题:

我已经设置了一个 PostgreSQL 函数和触发器,以便在

INSERT
表上有
UPDATE
DELETE
RiderDataPosition
操作时发送通知。然而,尽管我做出了努力,但我没有收到预期的任何通知。我正在寻求有关解决此问题的指导。我的最终结果是,当“RiderDataPosition”表中的某些内容发生变化时,我希望收到通知。

更新

向数据库发送查询

NOTIFY RiderPositionUpdate
时,我的测试应用程序收到响应。这意味着触发器出了问题!

问题描述:

我有一个在 Docker 容器中运行的 PostgreSQL 数据库,并且我使用的是最新版本。目标是每当

RiderPositionUpdate
表发生更改时向
RiderDataPosition
通道发送通知。这是我到目前为止所做的:

  1. 通知功能:

    我创建了一个通知功能,如下所示:

    CREATE OR REPLACE FUNCTION "TrackSolutionsCore".notify_rider_position_change()
    RETURNS TRIGGER AS $$
    BEGIN
        IF TG_OP = 'INSERT' THEN
            PERFORM pg_notify('RiderPositionUpdate', json_build_object('operation', 'insert', 'record_id', NEW."TransponderId")::text);
            RAISE NOTICE 'Inserted record with TransponderId %', NEW."TransponderId";
            RETURN NEW;
        ELSIF TG_OP = 'UPDATE' THEN
            PERFORM pg_notify('RiderPositionUpdate', json_build_object('operation', 'update', 'record_id', NEW."TransponderId")::text);
            RAISE NOTICE 'Updated record with TransponderId %', NEW."TransponderId";
            RETURN NEW;
        ELSIF TG_OP = 'DELETE' THEN
            PERFORM pg_notify('RiderPositionUpdate', json_build_object('operation', 'delete', 'record_id', OLD."TransponderId")::text);
            RAISE NOTICE 'Deleted record with TransponderId %', OLD."TransponderId";
            RETURN OLD;
        END IF;
    END;
    $$ LANGUAGE plpgsql;
    
  2. 触发器:

    我在

    AFTER INSERT
    表上为
    AFTER UPDATE
    AFTER DELETE
    RiderDataPosition
    操作创建了触发器。以下是其中一个触发器的示例:

    CREATE TRIGGER rider_data_position_insert_trigger
    AFTER INSERT ON "TrackSolutionsCore"."RiderDataPosition"
    FOR EACH ROW
    EXECUTE FUNCTION "TrackSolutionsCore".notify_rider_position_change();
    
  3. 表结构:

    RiderDataPosition
    表具有以下结构:

    CREATE TABLE "RiderDataPosition"
    (
        "TransponderId" integer generated by default as identity
            constraint "PK_RiderDataPosition"
                primary key,
        -- Other columns...
    );
    

面临的问题:

尽管设置了这些触发器和通知功能,但当我对

RiderPositionUpdate
表执行 CRUD 操作时,我在
RiderDataPosition
通道上没有收到任何通知。我尝试使用
NotificationEventHandler
通过 C# 应用程序接收这些通知,并通过在控制台中执行
LISTEN "RiderPositionUpdate"
直接通过 DataGrip 接收这些通知,但这两种方法都不会产生结果。

环境:

  • PostgreSQL 版本:[16]
  • Docker 引擎:[v24.0.6]

测试申请

using Npgsql;

var conn = new NpgsqlConnection("connectionString");
conn.Open();
conn.Notification += (o, e) => Console.WriteLine("Received notification");

using (var cmd = new NpgsqlCommand("LISTEN RiderPositionUpdate", conn)) {
    cmd.ExecuteNonQuery();
}

while (true) {
    conn.Wait();   // Thread will block here
}

向表中插入新记录后 DataGrip 中的输出

问题:

  1. 可能是什么原因导致此问题,如何进一步排除故障?
  2. 我应该检查任何特定的 PostgreSQL 配置或 Docker 设置以确保通知正常工作吗?
  3. 有没有办法验证触发器和函数是否正在发送通知,也许通过 PostgreSQL 日志或其他方法?
  4. 设置 PostgreSQL 触发器和通知函数时是否存在我可能忽略的常见陷阱或错误?

任何有关如何诊断和解决此问题的见解或指导将不胜感激。谢谢!

postgresql npgsql
1个回答
0
投票

您的大小写不匹配。如果您的频道名称包含真正的大写字母,则该名称必须在 LISTEN 命令中用双引号引起来。您的 NOTIFY 命令可与您的 LISTEN 配合使用,因为它会像 LISTEN 一样对通道名称进行大小写折叠,而 pg_notify 不会对其第一个参数进行大小写字段处理,因此它不起作用。

但更好的是,更改您的频道名称,使其中没有大写字母。

© www.soinside.com 2019 - 2024. All rights reserved.