Npgsql: подготовленное утверждение "_p1" не существует - PullRequest
0 голосов
/ 24 сентября 2018

Я пытаюсь загрузить данные запаса 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 голосов
/ 24 сентября 2018

Вам не хватает скобок вокруг вводимых значений.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)
...