Невозможно определить тип параметра массива, если его значение равно нулю - PullRequest
1 голос
/ 28 апреля 2020

Использование PostgreSQL базы данных и Dapper.

Вот минимальный пример ошибочного кода:

await using var connection = new NpgsqlConnection(_configuration.ConnectionString);

return await connection.QueryAsync<Diamond>(
  @"SELECT
      id,
      name
    FROM
      product
    WHERE
      @Names IS NULL OR name = ANY(@Names);",
  new
  {
      Names = Names,
  });

Это прекрасно работает, если Names = new { "Tom", "Dick", "Harry" }.

Однако он терпит неудачу, если Names = (string[]) null.

Ошибка, которую я получаю:

Npgsql.PostgresException (0x80004005): 42P18: could not determine data type of parameter $1
   at Npgsql.NpgsqlConnector.<>c__DisplayClass160_0.<<DoReadMessage>g__ReadMessageLong|0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Npgsql.NpgsqlConnector.<>c__DisplayClass160_0.<<DoReadMessage>g__ReadMessageLong|0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Npgsql.NpgsqlDataReader.NextResult(Boolean async, Boolean isConsuming)
   at Npgsql.NpgsqlCommand.ExecuteReaderAsync(CommandBehavior behavior, Boolean async, CancellationToken cancellationToken)
   at Npgsql.NpgsqlCommand.ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken)
   at Dapper.SqlMapper.QueryAsync[T](IDbConnection cnn, Type effectiveType, CommandDefinition command) in /_/Dapper/SqlMapper.Async.cs:line 419

Можно ли отправлять параметры массива NULL в Dapper на PostgreSQL, или мне нужно найти обходной путь?

1 Ответ

1 голос
/ 01 мая 2020

@ PeterCsala был прав. Проблема заключалась в том, что PostgreSQL подготавливает сторону сервера запросов, поэтому приведение параметра в C# world не помогает. Приведение должно быть сделано в SQL мире.

Рабочий код становится:

await using var connection = new NpgsqlConnection(_configuration.ConnectionString);

return await connection.QueryAsync<Diamond>(
  @"SELECT
      id,
      name
    FROM
      product
    WHERE
      @Names::text[] IS NULL OR name = ANY(@Names);",
  new
  {
      Names = Names,
  });
...