Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通过Npgsql调用时,“Upsert”/Merge函数的数据提交失败_C#_.net_Postgresql_Transactions_Npgsql - Fatal编程技术网

C# 通过Npgsql调用时,“Upsert”/Merge函数的数据提交失败

C# 通过Npgsql调用时,“Upsert”/Merge函数的数据提交失败,c#,.net,postgresql,transactions,npgsql,C#,.net,Postgresql,Transactions,Npgsql,我在Postgres 9.4中使用Npgsql 3.0.3。以下是我在Postgres中的代码: CREATE TABLE temp_test ( id serial NOT NULL, name text, CONSTRAINT temp_test_pk PRIMARY KEY (id) ) 以及Upsert/merge函数,该函数将更改的记录作为refcursor返回: CREATE OR REPLACE FUNCTION test_save( v_ref refcur

我在Postgres 9.4中使用Npgsql 3.0.3。以下是我在Postgres中的代码:

CREATE TABLE temp_test
(
  id serial NOT NULL,
  name text,
  CONSTRAINT temp_test_pk PRIMARY KEY (id)
)
以及Upsert/merge函数,该函数将更改的记录作为refcursor返回:

CREATE OR REPLACE FUNCTION test_save(
    v_ref refcursor,
    iv_id integer,
    v_name character varying)
  RETURNS refcursor AS
$BODY$ 
DECLARE
  v_ref alias for $1;
  v_id integer := iv_id;
BEGIN

  UPDATE onepm.temp_test
  SET name   = v_name
  WHERE id         = v_id;
  IF NOT FOUND THEN
  INSERT INTO onepm.temp_test
      (name)
  VALUES
      (v_name)
  RETURNING id INTO v_id;
  END IF;

  OPEN v_ref FOR
  SELECT id 
       , name
  FROM onepm.temp_test
  WHERE id = v_id;

  RETURN v_ref;
END;

$BODY$
  LANGUAGE plpgsql;
在.net项目中,我有以下返回IDatareader的函数:

public static IDataReader ExecuteReader()
        {
            NpgsqlConnection conn = new NpgsqlConnection(connectionString);
            conn.Open();

            NpgsqlTransaction _tran = conn.BeginTransaction();

            NpgsqlCommand cmd = conn.CreateCommand();
            cmd.CommandType = CommandType.Text;
            cmd.CommandText = "SELECT onepm.test_save(@ref, @id, @name)";

            NpgsqlParameter _p = new NpgsqlParameter();
            _p.ParameterName = "@ref";
            _p.NpgsqlDbType = NpgsqlDbType.Refcursor;
            _p.NpgsqlValue = "ref";
            _p.Direction = ParameterDirection.InputOutput;
            cmd.Parameters.Add(_p);

            cmd.Parameters.Add(new NpgsqlParameter("@id", 1));
            cmd.Parameters.Add(new NpgsqlParameter("@name", "test"));

            cmd.ExecuteNonQuery();
            cmd.CommandText = "fetch all in \"ref\"";
            cmd.CommandType = CommandType.Text;

            return cmd.ExecuteReader();
        }
这一切都很好,我确实在读卡器中接收插入或更新的记录,只是数据从未提交到表中-在pgAdmin中找不到数据。如果我在pgAdmin中调用相同的函数,一切正常-记录已提交:

SELECT onepm.test_save('v_ref', 1, 'xxxxxx');

FETCH ALL IN "v_ref";

谢谢你的帮助

嗯,我认为您需要提交您启动的事务


不管怎样,您可能还想看看PostgreSQL 9.5的新内置upsert功能…

谢谢您的回答!问题是,如果我提交了事务,我就失去了获取数据的能力。有没有一种方法可以用HOLD定义refcursor?嗯,函数没有真正的理由返回refcursor-您可以修改它以返回一个简单的表,请参见。然后,您可以在一个SQL调用中调用函数SELECT*FROM onepm.test\u save…,并可以完全删除BeginTransaction…谢谢,这需要定义返回表。我们需要db在插入时计算的值的新记录。。。Npgsql会用新的upsert语句以不同的方式处理这个问题吗?您还可以返回一条记录,请参阅。此处记录了PG 9.5 upsert功能:。Npgsql不知道也不关心它,它只是提供了它。虽然不确定它是否适合您尝试执行的操作,但返回记录也是半令人满意的,因为我们必须再次将记录类型修改为类似列的内容。我回到最初的问题:在Npgsql中从游标获取数据之后,是否有方法控制提交?直接打电话似乎效果不错。。无论如何谢谢你!