EF Core conversion and non nullable type converted to a nullable primitive

Viewed 682

I have a class MyClass that has a non nullable property Maybe<int> MyMproperty.

#nullable enable
public class MyClass
{
    public long Id { get; set; }
    public Maybe<int> MyProperty { get; set; }
}
#nullable restore

I declare and use en EF conversion in my MyContext:

builderEntity.Property(o => o.MyProperty).HasMaybeIntConversion();


public static PropertyBuilder<Maybe<int>> HasMaybeIntConversion(this PropertyBuilder<Maybe<int>> property)
        => property.HasConversion(
            x => x.Select(i => (int?)i).GetValueOrFallback(null),
            x=> x.HasValue 
                ? Maybe.From(x.Value) 
                : Maybe<int>.None);

The idea is to persist null for Maybe.None and to load Maybe.None from null.

However this doesn't work. When EF sees null in the database, it sets null to MyProperty (which is non nullable) without using the conversion rule.

To make it work I have to do the following changes:

#nullable enable
public class MyClass
{
    public long Id { get; set; }
    public Maybe<int> MyProperty => MyPropertyNullable  ?? Maybe<int>.None;
    public Maybe<int>? MyPropertyNullable { get; set; }
}
#nullable restore

and in MyContext:

builderEntity.Property(o => o.MyPropertyNullable).HasMaybeIntConversion().HasColumnName(nameof(MyClass.MyProperty));

I find it quite heavy and ugly.

Would anyone know of a simpler way of achieving the same result?

1 Answers

Unfortunately, this is a limitation of EF Core. If the underlying database column is nullable, the mapped property must also be nullable.
If the value fetched from the database is null, EF skips the registered conversion method altogether.

The issue is tracked here.

value converters do not generally allow the conversion of null to some other value. This is because the same value converter can be used for both nullable and non-nullable type.

Related