npg sql говорит, что перечисление не зарегистрировано - PullRequest
1 голос
/ 26 мая 2020

Я пытаюсь вставить данные с перечислениями через Npg sql. Сначала все работало нормально, но я заметил, что некоторые из моих перечислений не работают. Я сопоставил все свои перечисления c# с перечислениями postgres, но при попытке их использования некоторые из них выдают следующее сообщение:

Тип перечисления CLR One_More_Enum должен быть зарегистрирован в Npgsql перед использованием обратитесь к документации

Я думаю, что сопоставил свои перечисления в соответствии с документацией. По крайней мере, перечисления Some_Enum и Another_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;

Я приготовил все, чтобы вы могли проверить это самостоятельно, не прилагая больших усилий. При такой настройке я получаю описанную выше ошибку.

Sql:

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();
        }
    }


} 

Есть идеи, что я делаю не так?

1 Ответ

0 голосов
/ 19 августа 2020

Я не нашел хорошего решения этой проблемы, но я нашел, что вызывает проблему и как ее обойти.

Когда у меня есть две идентичные схемы в моей базе данных, эта проблема возникает. Кажется, Npg sql сбивает с толку, из какой схемы он должен брать перечисление, и выбирает неправильную. (Например, я делаю вставку в schema_a, а перечисление используется из schema_b) Я пытался использовать set search_path, но это, похоже, не помогло.

На данный момент у меня есть только один (из то же самое) в моей базе данных, чтобы все работало. Может быть, кто-то с большим опытом работы с npgsl знает, как решить эту проблему.

Проблема в том, что npg sql не понимает, какое перечисление следует использовать.

...