Npgsql:预处理语句“ _p1”不存在

时间:2018-09-23 23:48:36

标签: c# postgresql npgsql

我正在尝试使用以下方法将EOD库存数据加载到表中:

    public async Task<long> BulkInsertEodData(IEnumerable<EodData> records, string symbol)
    {
        var recordsProcessed = 0L;
        using (var conn = await OpenConnection())
        using (var trans = conn.BeginTransaction())
        using (var comm = _factory.CreateCommand())
        {
            try
            {
                comm.Connection = conn;
                comm.Transaction = trans;
                comm.CommandText = INSERT_EOD;
                var ps = AddParametersToInsertEodQuery(comm);
                foreach (var p in ps) comm.Parameters.Add(p);
                comm.Prepare();

                foreach (var record in records)
                {
                    comm.Parameters["@date_id"].Value = record.DateId;
                    comm.Parameters["@symbol"].Value = symbol.ToUpper();
                    comm.Parameters["@eod_close"].Value = record.EodClose;
                    comm.Parameters["@eod_high"].Value = record.EodHigh;
                    comm.Parameters["@eod_low"].Value = record.EodLow;
                    comm.Parameters["@eod_volume"].Value = record.EodVolume;
                    comm.Parameters["@eod_open"].Value = record.EodOpen;
                    comm.Parameters["@eod_split"].Value = record.EodSplit;
                    comm.Parameters["@eod_dividend"].Value = record.EodDividend;
                    comm.Parameters["@last_modified"].Value = DateTime.UtcNow;
                    await comm.ExecuteNonQueryAsync();
                    recordsProcessed++;
                }

                trans.Commit();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "BulkInsertEodData(IEnumerable<EodData>)");
                trans.Rollback();
            }
        }

        return recordsProcessed;
    }

查询文本如下:

        INSERT INTO public.eod_datas(
            date_id, 
            stock_id, 
            eod_open, 
            eod_close, 
            eod_low, 
            eod_high, 
            eod_volume, 
            eod_dividend, 
            eod_split, 
            last_modified_timestamp
        )
        values
            @date_id, 
            (select s.id from stocks s where s.symbol = @symbol limit 1), 
            @eod_open, 
            @eod_clos, 
            @eod_low, 
            @eod_high, 
            @eod_volume, 
            @eod_dividend, 
            @eod_split, 
            current_timestamp
        on conflict (date_id, stock_id)
        do update set 
            eod_open = @eod_open, 
            eod_close = @eod_close, 
            eod_low = @eod_low, 
            eod_high = @eod_high, 
            eod_volume = @eod_volume, 
            eod_dividend = @eod_dividend, 
            eod_split = @eod_split, 
            last_modified_timestamp = current_timestamp;

这不是我第一次使用准备好的语句,但这次我做了一些不同的事情(.NET Core,使用DbProviderFactory),并且得到了奇怪的结果。

通过这种方法的前几次,我发现Npgsql.PostgresException (0x80004005): 42601: syntax error at or near "$1"的效果是一个错误,它本身是相当神秘的,但最神秘的是该错误实际上已经消失经过两次方法调用后,我开始不断得到Npgsql.PostgresException (0x80004005): 26000: prepared statement "_p1" does not exist后缀。

有人可以解释这种行为吗?我究竟做错了什么?在哪里可以获得有关“ $ 1”的更多详细信息?

1 个答案:

答案 0 :(得分:1)

您缺少要插入的值周围的括号。可悲的是,Postgres不会告诉您它期望在$ 1之前出现括号。

正确的语法:

values (
    @date_id, 
    (select s.id from stocks s where s.symbol = @symbol limit 1), 
    @eod_open, 
    @eod_clos, 
    @eod_low, 
    @eod_high, 
    @eod_volume, 
    @eod_dividend, 
    @eod_split, 
    current_timestamp)
on conflict (date_id, stock_id)