首页 > 解决方案 > npgsql 说枚举未注册

问题描述

我正在尝试通过 Npgsql 插入一些带有枚举的数据。起初,一切正常,但我注意到,我的一些枚举不起作用。我已将所有 c# 枚举映射到 postgres 枚举,但是在尝试使用它们时,其中一些给我以下消息:

CLR 枚举类型 One_More_Enum 使用前必须在 Npgsql 中注册,请参考文档

我想我已经根据文档映射了我的枚举。至少枚举Some_EnumAnother_Enum工作都很好。

这是我的代码:

//Enum declaration
public enum Some_Enum
{
    [PgName("SOME_VALUE")]
    SOME_VALUE,
    [PgName("ANOTHER_VALUE")]
    ANOTHER_VALUE,
    [PgName("ONE_MORE_VALUE")]
    ONE_MORE_VALUE
}

public enum Other_Enum
{
    [PgName("SOME_VALUE")]
    SOME_VALUE,
    [PgName("ANOTHER_VALUE")]
    ANOTHER_VALUE,
    [PgName("ONE_MORE_VALUE")]
    ONE_MORE_VALUE
}

public enum One_More_Enum
{
    [PgName("SOME_VALUE")]
    SOME_VALUE,
    [PgName("ANOTHER_VALUE")]
    ANOTHER_VALUE,
    [PgName("ONE_MORE_VALUE")]
    ONE_MORE_VALUE
}

//Register my enums according to the documentation
NpgsqlConnection.GlobalTypeMapper.MapEnum<Some_Enum>("some_enum");
NpgsqlConnection.GlobalTypeMapper.MapEnum<Other_Enum>("other_enum");
NpgsqlConnection.GlobalTypeMapper.MapEnum<One_More_Enum>("one_more_enum");

using (var connection = new Npgsql.NpgsqlConnection(CONNECTION_STRING))
{
    connection.Open();

    var command = connection.CreateCommand();
    command.CommandText = $"INSERT INTO TABLE_A (NAME, SOME_ENUM) VALUES (@NAME, @SOME_ENUM) RETURNING ID";
    command.Parameters.AddWithValue("NAME", "Foo Bar");
    command.Parameters.AddWithValue("SOME_ENUM", Some_Enum.SOME_VALUE);
    var A_id = command.ExecuteScalar(); //Works fine...

    command.Parameters.Clear();

    command.CommandText = $"INSERT INTO TABLE_B (A_ID, NAME, FOO, BAR, OTHER_ENUM)" +
                        $"VALUES (@A_ID, @NAME, @FOO, @BAR, @OTHER_ENUM) RETURNING ID";
    command.Parameters.AddWithValue("NAME", "Some Name Bla Bla");
    command.Parameters.AddWithValue("A_ID", A_id);
    command.Parameters.AddWithValue("FOO", false);
    command.Parameters.AddWithValue("BAR", false);
    command.Parameters.AddWithValue("OTHER_ENUM", Other_Enum.ANOTHER_VALUE);
    var B_id = command.ExecuteScalar(); //Works fine

    command.Parameters.Clear();

    command.CommandText = $"INSERT INTO TABLE_C (B_ID, NAME, ONE_MORE_ENUM) VALUES (@B_ID, @NAME @ONE_MORE_ENUM) RETURNING ID";
    command.Parameters.AddWithValue("B_ID", B_id);
    command.Parameters.AddWithValue("NAME", "Hey Ho Name");
    command.Parameters.AddWithValue("ONE_MORE_ENUM", One_More_Enum.ONE_MORE_VALUE);
    var D_id = command.ExecuteScalar(); //!!! Error is thrown here...
}

我在堆栈上发现了这个问题,问题似乎是通过注册枚举而不是全局而是通过连接来解决的(但是问题的发布者认为这并没有解决他的问题(看看他的回答))。我试过这样:

//Register my enums according to the documentation
NpgsqlConnection.GlobalTypeMapper.MapEnum<Some_Enum>("some_enum");
NpgsqlConnection.GlobalTypeMapper.MapEnum<Other_Enum>("other_enum");
//NpgsqlConnection.GlobalTypeMapper.MapEnum<One_More_Enum>("one_more_enum");

using (var connection = new Npgsql.NpgsqlConnection(CONNECTION_STRING))
{
    connection.Open();
    connection.TypeMapper.MapEnum<One_More_Enum>("one_more_enum");
    connection.ReloadTypes();

    //...
}

但我得到同样的错误信息......


这是 postgre 中枚举的声明:

CREATE TYPE SOME_ENUM AS ENUM ('SOME_VALUE', 'ANOTHER_VALUE', 'ONE_MORE_VALUE');
ALTER TYPE SOME_ENUM OWNER TO postgres;
CREATE TYPE ANOTHER_ENUM AS ENUM ('SOME_VALUE', 'ANOTHER_VALUE', 'ONE_MORE_VALUE');
ALTER TYPE ANOTHER_ENUM OWNER TO postgres;
CREATE TYPE ONE_MORE_ENUM AS ENUM ('SOME_VALUE', 'ANOTHER_VALUE', 'ONE_MORE_VALUE');
ALTER TYPE ONE_MORE_ENUM OWNER TO postgres;

我已经简化了所有内容,您应该能够自己测试,而无需付出很多努力。通过此设置,我得到了上述错误。

数据:

CREATE TYPE GRABART_MULTIPLIKATOR AS ENUM ('NICHT_MULTIPLIZIEREN', 'ANZAHL_GRABSTELLEN', 'FLAECHE');
ALTER TYPE GRABART_MULTIPLIKATOR OWNER TO postgres;

CREATE TABLE grab_art (
    id                                          SERIAL                 NOT NULL
        CONSTRAINT grabart_pkey
            PRIMARY KEY,
    bezeichnung                                 TEXT,
    multiplikator                               GRABART_MULTIPLIKATOR
);

ALTER TABLE grab_art
    OWNER TO postgres;

C#:

class Program
{
    const string CONNECTION_STRING = "Server=localhost;Port=5432;Database=my_db;search path=my_demo;User ID=postgres;Password=pw;";

    public enum Grabart_Multiplikator
    {
        [PgName("NICHT_MULTIPLIZIEREN")]
        NICHT_MULTIPLIZIEREN,
        [PgName("ANZAHL_GRABSTELLEN")]
        ANZAHL_GRABSTELLEN,
        [PgName("FLAECHE")]
        FLAECHE
    }

    static void Main(string[] args)
    {
        try
        {
            NpgsqlConnection.GlobalTypeMapper.MapEnum<Grabart_Multiplikator>("grabart_multiplikator");

            using (var connection = new Npgsql.NpgsqlConnection(CONNECTION_STRING))
            {
                connection.Open();

                var command = connection.CreateCommand();
                command.CommandText = $"INSERT INTO GRAB_ART (BEZEICHNUNG, MULTIPLIKATOR) VALUES (@BEZEICHNUNG, @MULTIPLIKATOR) RETURNING ID";
                command.Parameters.AddWithValue("BEZEICHNUNG", "Neuer Rechtsträger");
                command.Parameters.AddWithValue("MULTIPLIKATOR", Grabart_Multiplikator.FLAECHE);
                var grabart_id = command.ExecuteScalar();

                command.Parameters.Clear();


                Console.WriteLine($"Success...");
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
        finally
        {
            Console.WriteLine("Press any key to exit");
            Console.ReadKey();
        }
    }


} 

任何想法我做错了什么?

标签: c#postgresqlenumsnpgsql

解决方案


我也有这个问题。在不同的模式中具有相同名称的两个枚举。

只需在您的实体配置中设置“schema.enum”:

connection.TypeMapper.MapEnum<One_More_Enum>("schema.one_more_enum");

这个对我有用!


推荐阅读