如何使用Dapper将JSON作为原始PostgreSQL类型传递给函数? [英] How do I pass JSON as a primitive PostgreSQL type to a function using Dapper?

查看:226
本文介绍了如何使用Dapper将JSON作为原始PostgreSQL类型传递给函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个PostgreSQL函数,它带有一个 json 类型的参数。使用Dapper,如何执行将对象传递给PostgreSQL函数的调用,以便PostgreSQL将类型识别为 json 而不是 text

I have a PostgreSQL function that takes in a parameter of type json. Using Dapper, how do I execute a call that passes the object to the PostgreSQL function such that PostgreSQL recognizes the type as json instead of as text?

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#集成测试



Broken Example C# Integration Test

[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



Supporting 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 表示解析。)

In this current iteration, I've added a SqlMapper.TypeHandler. (At the moment, I'm only concerned with passing the JArray to PostgreSQL, hence the NotImplmentedException for Parse.)

在此示例中,出现以下异常:

With this example, I get the following exception:


System.NotSupportedException :'Npgsql或PostgreSQL不支持CLR数组类型Newtonsoft.Json.Linq.JArray。如果您希望将其映射到PostgreSQL复合类型数组,则需要在使用前进行注册,请参考文档。'

System.NotSupportedException: 'The CLR array type Newtonsoft.Json.Linq.JArray isn't supported by Npgsql or your PostgreSQL. If you wish to map it to an PostgreSQL composite type array you need to register it before usage, please refer to the documentation.'

在过去的迭代中,我还尝试过使用 List< Hero> 类型处理程序,并让该类型处理程序处理Json转换。

In past iterations, I've also tried things like using a List<Hero> type handler and letting that type handler deal with the Json conversion.

我还尝试为Npgsql添加 Npgsql.Json.NET Nuget软件包扩展,并调用 conn.TypeMapper。在我的测试方法中使用UseJsonNet(),但这似乎没有任何效果。

I've also tried adding the Npgsql.Json.NET Nuget package extension for Npgsql and call conn.TypeMapper.UseJsonNet() in my test method, but that didn't seem to have any effect.

如果我执行任何操作来序列化对象

And if I do anything to serialize the object to a JSON string, then I get a different error (below), which makes sense.


Npgsql.PostgresException >: 42883:函数testfuncthattakesinjson(heroes => text)不存在

Npgsql.PostgresException: '42883: function testfuncthattakesinjson(heroes => text) does not exist'

因此,可以使用Dapper将JSON对象作为PostgreSQL原语传递给函数?

推荐答案

您可以使用Dapper的ICustomQueryParameter接口。

You can use Dapper's ICustomQueryParameter interface.

public class JsonParameter : ICustomQueryParameter
{
    private readonly string _value;

    public JsonParameter(string value)
    {
        _value = value;
    }

    public void AddParameter(IDbCommand command, string name)
    {
        var parameter = new NpgsqlParameter(name, NpgsqlDbType.Json);
        parameter.Value = _value;

        command.Parameters.Add(parameter);
    }
}

然后,您的Dapper呼叫将变为:

Then your Dapper call becomes:

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

这篇关于如何使用Dapper将JSON作为原始PostgreSQL类型传递给函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆