PG 批量写入数据报错

发布于 2021-11-27 23:05:55 字数 5130 浏览 705 评论 1

C#环境下一次性写1万多条数据,调用数据库接口之后有时候会报出以下错误信息:


2015/10/19 18:56:04  Tried to add too many fields to a copy record with 1 fields
2015/10/19 18:56:05  Tried to add too many fields to a copy record with 3 fields
2015/10/19 18:56:05  Tried to add too many fields to a copy record with 4 fields
以上是调试信息的一部分,调用同样的接口写入同种类型的数据,报出的错误稍微不同,但是错误类型是一样的。


接口中的逻辑:

1.先创建临时表

2.使用PG的bulk copy将数据批量写入临时表

PG bulk copy 代码如下:

using (PostgreSQLCopyDataToTempTableHelper copyHelper = new PostgreSQLCopyDataToTempTableHelper(conn, "COPY TEMP_WRITEFIXPERIOD(nodetype, nodeid, dataid, recordtime, periodtype, sourcetype, datavalue, maxvalue, minvalue, avgvalue) FROM STDIN"))
            {
                if (!copyHelper.Initialize())
                    return copyHelper.ErrorCode;
                try
                {
                    for (int i = 0; i < logs.Length; ++i)
                    {
                        copyHelper.AddValue(logs[i].nodeType);
                        copyHelper.AddValue(logs[i].nodeID);
                        copyHelper.AddValue(logs[i].dataID);
                        copyHelper.AddValue(logs[i].recordTime);
                        copyHelper.AddValue(logs[i].periodType);
                        copyHelper.AddValue(logs[i].sourceType);
                        copyHelper.AddValue(logs[i].dataValue);
                        copyHelper.AddValue(logs[i].maxValue);
                        copyHelper.AddValue(logs[i].minValue);
                        copyHelper.AddValue(logs[i].avgValue);
                        copyHelper.AddEndRow();
                    }
                }
                catch (System.Exception ex)
                {
                    Plugin.GlobalInformation.LastErrorString = ex.Message;
                    return (int)ErrorCode.SPCommonError;
                }

                return copyHelper.CopyDataToTempTable();
            }



其中
copyHelper.Initialize()执行批量处理的初始化工作,代码如下:
public bool Initialize()
        {
            try
            {
                npgsqlCommand = new NpgsqlCommand(copyDataToTempTableQuery, npgsqlConnection);
                npgsqlCopySerializer = new NpgsqlCopySerializer(npgsqlConnection);
                npgsqlCopyIn = new NpgsqlCopyIn(npgsqlCommand, npgsqlConnection, npgsqlCopySerializer.ToStream);
                npgsqlCopyIn.Start();
                return true;
            }
            catch (System.Exception ex)
            {
                Plugin.GlobalInformation.LastErrorString = ex.Message;
                errorCode = (int)DBInterfaceCommonLib.ErrorCode.SPCommonError;
                return false;
            }
        }



copyHelper.CopyDataToTempTable()执行批量将数据写入临时表的操作,代码如下:
public int CopyDataToTempTable()
        {
            try
            {
                npgsqlCopySerializer.Flush();
                npgsqlCopyIn.End();

                return (int)DBInterfaceCommonLib.ErrorCode.Success;
            }
            catch (NpgsqlException ex)
            {
                try
                {
                    npgsqlCopyIn.Cancel("Undo copy"); 
                }
                catch (Exception ex2)
                {
                    Plugin.GlobalInformation.LastErrorString = "Failed to cancel copy: " + ex2.Message + " Copy failure: " + ex.Message; 
                    return (int)DBInterfaceCommonLib.ErrorCode.SPCommonError;
                }
                Plugin.GlobalInformation.LastErrorString = ex.Message;
                return (int)DBInterfaceCommonLib.ErrorCode.SPCommonError;
            }
        }



说明一下:这个批量写入的数据库接口也不是每次都报错,有时候一次都不报,有时候次次都报,搞不懂是什么原因,可以保证临时表中的字段数量和要写入的数据的字段是一样的。但是跟踪调试的时候发现临时表的字段会变化,原因不明,创建临时表的代码如下:
public const string createTempTableForWriteFixPeriodDatas = @"CREATE TEMP TABLE TEMP_WRITEFIXPERIOD ( 
                        nodetype integer NOT NULL,
                        nodeid integer NOT NULL,
                        dataid integer NOT NULL,
                        recordtime timestamp without time zone NOT NULL,
                        periodtype smallint NOT NULL,
                        sourcetype smallint NOT NULL,
                        datavalue bigint,
                        maxvalue bigint,
                        minvalue bigint,
                        avgvalue bigint
                        )";

向临时表中添加数据的代码:

调试的时候在这一步报错:

提示的异常是:“Tried to add too many fields to a copy record with 1 fields ”。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

浮生未歇 2021-11-27 23:44:29

昨天试了一下,发现修改了CopyBufferSize之后不再报这个错误,暂时先这样吧。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文