Array of composite type as stored procedure input passed by C# Npgsql

帅比萌擦擦* 提交于 2021-02-06 13:59:54

问题


I've read several questions and topics related to the issue but none of them actually helped me to solve my problem and none of them actually were related to C#. And here is the actual problem:

I have a Postgre composite type:

CREATE TYPE law_relation_update_model AS (
   from_celex character varying,
   from_article character varying,
   to_celex character varying,
   to_article character varying,
   link_ids integer[],
   to_doc_par_id integer
);

And I have a stored procedure that is meant to accept an array of the following type:

CREATE OR REPLACE FUNCTION insert_law_relations(_items law_relation_update_model[])
RETURNS VOID
AS
$$
BEGIN

END;
$$
LANGUAGE PLPGSQL;

I've removed the body code since it's not relevant cause the following error is thrown at procedure invoke from C#:

malformed array literal

And an inner message of:

array value must start with “{” or dimension information

C# Model that is about to be passed (an array of it):

public class LawRelationUpdateModel
{
    public string FromCelex { get; set; }

    public string FromArticle { get; set; }

    public string ToCelex { get; set; }

    public string ToArticle { get; set; }

    public IEnumerable<int> LinkIds { get; set; } = new List<int>();

    public int ToDocParId { get; set; }
}

And the method that makes the call using Npgsql connector:

public static void InsertLawRelations(LawRelationUpdateModel[] updateModel)
{
    using (NpgsqlConnection conn = new NpgsqlConnection(connPG))
    {
        conn.Open();
        NpgsqlCommand comm = new NpgsqlCommand("insert_law_relations", conn);
        comm.CommandType = CommandType.StoredProcedure;
        var testParam = new NpgsqlParameter();
        testParam.DbType = DbType.Object;
        testParam.Value = updateModel;
        testParam.ParameterName = "_items";
        comm.Parameters.Add(testParam);

        comm.ExecuteNonQuery();
    }
}

Can it be a bug in the connector that somehow does not convert some single/double quotes or brackets correctly when passing?

Or something related to the fact that I asign DBType as an Object? If I don't I get the following error instead:

Can't cast LawRelationUpdateModel[] into any valid DbType.

Any help regarding the issue or other workarounds will be highly appreciated!


回答1:


Mapping your CLR Types

It is still possible, and in some cases necessary, to set up an explicit mapping for your CLR types. Doing so provides the following advantages:

You know longer need to specify the DataTypeName property on your parameter. Npgsql will infer the data type from your provided CLR type.

Untyped read methods such as NpgsqlDataReader.GetValue() will return your CLR type, instead of a dynamic object (see below). In general you should be using the typed NpgsqlDataReader.GetFieldValue(), so this shouldn't be important.

You can customize the name mapping on a per-type basis (see below). To set up a global mapping for all your connections, put this code before your first open:

 NpgsqlConnection.GlobalTypeMapper.MapEnum<SomeEnum>("some_enum");
 NpgsqlConnection.GlobalTypeMapper.MapComposite<SomeType>("some_composite");

This sets up a mapping between your CLR types SomeEnum and SomeType to the PostgreSQL types some_enum and some_composite.

If you don't want to set up a mapping for all your connections, you can set it up one connection only:

var conn = new NpgsqlConnection(...);
conn.TypeMapper.MapEnum<SomeEnum>("some_enum");
conn.TypeMapper.MapComposite<SomeType>("some_composite");

http://www.npgsql.org/doc/types/enums_and_composites.html



来源:https://stackoverflow.com/questions/45329077/array-of-composite-type-as-stored-procedure-input-passed-by-c-sharp-npgsql

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!