我在使用postgres枚举时遇到了一个奇怪的问题,在try 查询一个带有ENUM的表时出现错误,但前提是在同一会话中运行了CREATE命令.我不知道为什么会发生这种情况,这使得运行迁移脚本变得非常困难,因为我现在必须运行应用程序两次才能正常工作.

我认为这是某种缓存问题,我try 关闭连接池,但似乎也不起作用.

它很容易重现,所以我制作了一个代码样本:

using Dapper;
using Npgsql;

var connection = new NpgsqlConnection("Host=127.0.0.1;Port=5432;User ID=postgres;Password=password;Database=messaging;Include Error Detail=true;");
await connection.OpenAsync();

var tableCommand = new NpgsqlCommand()
{
    Connection = connection,
    CommandText = """
        CREATE TYPE message_type AS ENUM ('sms', 'email');
        CREATE TABLE message (
            id SERIAL PRIMARY KEY,
            type message_type NOT NULL
        );
        """
};

// Comment this line on a second run
await tableCommand.ExecuteNonQueryAsync();

var queryCommand = new NpgsqlCommand()
{
    Connection = connection,
    CommandText = """
        SELECT id, type
        FROM message;
        """
};

var reader = await queryCommand.ExecuteReaderAsync();
// The offending line
var parser = reader.GetRowParser<Message>();

class Message
{
    public int Id { get; set; }
    public string? Type { get; set; }
}

这将在第一次运行时产生以下错误:

System.InvalidCastException: 'Reading as 'System.Object' is not supported for fields having DataTypeName '.<unknown>''

Inner Exception
ArgumentException: A PostgreSQL type with the oid '0' was not found in the current database info

在第二次运行时(在注释掉CREATE命令时),我没有收到任何错误,一切都按预期运行.它似乎在第一次运行时看不到枚举存在,但在第二次运行时一切正常,因为建立连接时它已经在那里了.

我正在使用所有内容的最新版本(在 compose 本文时):

  • Postgres 16.1
  • .NET 8
  • Dapper是2.1.24.
  • Npgsql 8.0.1

推荐答案

必须使用await connection.ReloadTypesAsync();来重新加载在命令中创建的新类型.

这是一个使用Dapper而不是命令的示例,但您只需在代码中插入reLoad Types命令即可:

await connection.ExecuteAsync("""
    CREATE TYPE message_type AS ENUM ('sms', 'email');
    CREATE TABLE message (
        id SERIAL PRIMARY KEY,
        type message_type NOT NULL
    );
    """);

await connection.ReloadTypesAsync(); // add this to your code

var parser = await connection.QueryAsync<Message>("""
       SELECT id, type
       FROM message;
       """);  

NpgsqlConnection中记载了此方法刷新连接中加载的类型的缓存.

Csharp相关问答推荐

PostingAsJsonAschange在从调用的方法返回时给出500错误

Autofac:如何防止丢弃通过ServicCollection注册的服务?

在包含空项的列表上使用具有断言T的摘要表

利用.NET 8中的AddStandardResilienceDeliveries和AddStandardHedgingDeliveries实现Resiliency

.NET最小API映射将T参数列表为[FromQuery]

当打印一行x个项目时,如何打印最后一行项目?

C#中使用BouncyCastle计算CMac

当通过Google的Gmail Api发送邮件时,签名会产生dkim = neutral(正文散列未验证)'

如何定义EFCore中的多个穿透

为什么任务需要在内部使用ManualResetEventSlim?

与C#中的Zip列表并行

如何将MongoDB序列化程序设置为内部对象属性

如何将字符串变量传递给JObject C#-无法加载文件或程序集';System.Text.Json

DbContext-传递自定义配置选项

如何向事件添加成员

为什么此名称不再被识别?名称不存在于当前上下文中?

DropDownListFor未显示选定值

C#USB条形码 scanner 在第二次扫描时未写入行尾字符

Xamarin.Forms项目中缺少MainPage.xaml

如何为控制器PUT操作绑定对象数组