簡體   English   中英

如何使用Dapper將JSON作為原始PostgreSQL類型傳遞給函數?

[英]How do I pass JSON as a primitive PostgreSQL type to a function using Dapper?

我有一個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,因此ParseNotImplmentedException 。)

在這個例子中,我得到以下異常:

System.NotSupportedException :'Npgsql或PostgreSQL不支持CLR數組類型Newtonsoft.Json.Linq.JArray。 如果您希望將其映射到PostgreSQL復合類型數組,則需要在使用前注冊它,請參閱文檔。

在過去的迭代中,我還嘗試過使用List<Hero>類型處理程序並讓該類型處理程序處理Json轉換。

我也嘗試為Npgsql添加Npgsql.Json.NET Nuget包擴展,並在我的測試方法中調用conn.TypeMapper.UseJsonNet() ,但這似乎沒有任何效果。

如果我做任何事情來將對象序列化為JSON字符串,那么我會得到一個不同的錯誤(下面),這是有道理的。

Npgsql.PostgresException :'42883:function testfuncthattakesinjson(heroes => text)不存在'

那么, 有可能使用Dapper將JSON對象作為PostgreSQL原語傳遞給函數嗎?

您可以使用Dapper的ICustomQueryParameter接口。

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調用成為:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM