Как передать JSON как примитивный тип PostgreSQL функции, использующей Dapper? - PullRequest
0 голосов
/ 24 мая 2019

У меня есть функция PostgreSQL, которая принимает параметр типа json.Используя Dapper, как мне выполнить вызов, который передает объект в функцию PostgreSQL, так что PostgreSQL распознает тип как json вместо text?

Пример функции PostgreSQL, которая принимает тип json

CREATE OR REPLACE FUNCTION testfuncthattakesinjson(heroes json)
    RETURNS SETOF characters 
    LANGUAGE 'sql'

    STABLE
    ROWS 100
AS $BODY$

    SELECT  c.*
    FROM    characters c
    JOIN    json_array_elements(heroes) j
    ON      c.first_name = j->>'first_name'
    AND     c.last_name = j->>'last_name';

$BODY$;

Разбитый пример Тест интеграции C #

[Test]
public void Query_CallFunctionThatTakesInJsonParameter_FunctionUsesJsonType()
{
    using (var conn = new NpgsqlConnection(Db.GetConnectionStringToDatabase()))
    {
        var funcName = "testfuncthattakesinjson";
        var expect = CharacterTestData.Where(character => character.id <= 3);
        var jsonObj = JArray.FromObject(CharacterTestData
            .Where(character => character.id <= 3)
            .Select(character => new Hero(character))
            .ToList());

        SqlMapper.AddTypeHandler(new JArrayTypeHandler());

        // Act 
        var results = conn.Query<Character>(funcName, new
        {
            heroes = jsonObj
        }, commandType: CommandType.StoredProcedure);

        // Assert
        CollectionAssert.AreEquivalent(expect, results);
    }
}

Поддержка JArrayTypeHandler

internal class JArrayTypeHandler : SqlMapper.TypeHandler<JArray>
{
    public override JArray Parse(object value)
    {
        throw new NotImplementedException();
    }

    public override void SetValue(IDbDataParameter parameter, JArray value)
    {
        parameter.Value = value;
    }
}

В этомтекущую итерацию, я добавил SqlMapper.TypeHandler.(В настоящее время я занимаюсь только передачей JArray в PostgreSQL, следовательно, NotImplmentedException для Parse.)

В этом примере я получаю следующееисключение:

System.NotSupportedException : 'Тип массива CLR Newtonsoft.Json.Linq.JArray не поддерживается Npgsql или вашим PostgreSQL.Если вы хотите отобразить его в массив составных типов PostgreSQL, вам необходимо зарегистрировать его перед использованием, пожалуйста, обратитесь к документации. '

В прошлых итерациях я также пробовал такие вещи, как использование List<Hero> обработчик типов и разрешение этому обработчику типов работать с преобразованием Json.

Я также пытался добавить расширение Npgsql.Json.NET Nuget для Npgsql и вызвать conn.TypeMapper.UseJsonNet() в моем тестовом методе, но это не так.Это, кажется, не имеет никакого эффекта.

И если я сделаю что-нибудь для сериализации объекта в строку JSON, то получу другую ошибку (ниже), которая имеет смысл.

Npgsql.PostgresException : '42883: функция testfuncthattakesinjson (heroes => text) не существует'

Таким образом, можно использовать Dapper для передачи объекта JSONкак примитив PostgreSQL для функции?

...