Using PostgreSQL database and Dapper.
Here's a minimal example of the failing code:
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,
});
This works fine if Names = new { "Tom", "Dick", "Harry" }
.
However it fails if Names = (string[]) null
.
The error I get is:
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
Is it possible to send nullable array parameters in Dapper to PostgreSQL, or do I need to find a workaround?
@PeterCsala was correct. The issue was that PostgreSQL prepares the query server side, so casting the parameter in C# world doesn't help. The casting must be done in SQL world.
The working code becomes:
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,
});