Repository: npgsql/npgsql

Issue #1965: Support writing Nullable<T> in COPY binary importer
Created: 2018-05-31T11:35:49Z
Steps to reproduce
using (var loader = conn.BeginBinaryImport(query))
{
    foreach (var price in items)
    {
        loader.StartRow();
        loader.Write(price.Id, NpgsqlDbType.Integer);
        loader.Write(price.Date, NpgsqlDbType.Date);
        loader.Write(price.Value, NpgsqlDbType.Numeric);   <--- exception here
    }

    loader.Complete();
}

public struct Price
{
    public int Id { get; set; }
    public DateTime Date { get; set; }
    public decimal? Value { get; set; }
}


The issue
After updating npgsql to 4.0.0:
When type of Value is nullable decimal I'm getting an exception while using binary import.
`Value' = 627.99M.
Exception message:
System.InvalidCastException: 'Can't write CLR type System.Nullable`1[System.Decimal] to database type numeric'
Stack trace:
   at Npgsql.TypeHandling.NpgsqlSimpleTypeHandler`1.ValidateAndGetLength[TAny](TAny value, NpgsqlLengthCache& lengthCache, NpgsqlParameter parameter) in C:\projects\npgsql\src\Npgsql\TypeHandling\NpgsqlSimpleTypeHandler.cs:line 171
   at Npgsql.NpgsqlParameter`1.ValidateAndGetLength() in C:\projects\npgsql\src\Npgsql\NpgsqlParameter`.cs:line 89
   at Npgsql.NpgsqlBinaryImporter.Write[T](T value, NpgsqlParameter param) in C:\projects\npgsql\src\Npgsql\NpgsqlBinaryImporter.cs:line 244
   at Npgsql.NpgsqlBinaryImporter.Write[T](T value, NpgsqlDbType npgsqlDbType) in C:\projects\npgsql\src\Npgsql\NpgsqlBinaryImporter.cs:line 189

Further technical details
Npgsql version: 4.0.0
PostgreSQL version: 10
Operating system: W10 64bit

Duplicate issue #4417: NpgsqlBinaryImporter.write(...) is throwing an exception when a nullable type value is passed.
Created: 2022-04-16T16:10:53Z
Steps to reproduce
using var cmd = new NpgsqlCommand("create table if not exists person(house_number integer)", conn);
cmd.ExecuteNonQuery();

using var writer = conn.BeginBinaryImport("COPY person(house_number) FROM STDIN BINARY");
var person = new Person(Guid.NewGuid(), 1) ;
writer.StartRow();
writer.Write(person.HouseNumber, NpgsqlDbType.Integer);
writer.Complete();

public record Person (Guid Id, int? HouseNumber);
The issue
NpgsqlBinaryImporter.write(...) is throwing an exception when a nullable type value is passed as below.
Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
   at Npgsql.Internal.TypeHandling.NpgsqlTypeHandler.ValidateAndGetLengthCustom[TAny](TAny value, NpgsqlLengthCache& lengthCache, NpgsqlParameter parameter)
   at Npgsql.NpgsqlParameter`1.ValidateAndGetLength()
   at Npgsql.NpgsqlBinaryImporter.Write[T](T value, NpgsqlParameter param, Boolean async, CancellationToken cancellationToken)
   at Npgsql.NpgsqlBinaryImporter.Write[T](T value, NpgsqlDbType npgsqlDbType)
   at Program.<Main>$(String[] args) in /Users/babuannamalai/tinker_room/npgsql_bulkinsert_test/npgsql_bulkinsert_test/Program.cs:line 16

Further technical details
Npgsql version: 6.x and 7.x
PostgreSQL version: 14
Operating system: macOS 12.3.1 (21E258)

Closing comment (2022-04-17T19:21:08Z): This is tracked by #1965 - we've generally not received lots of interest in that, especially when it's very easy to check for null and call WriteNull instead.