efcore.pg icon indicating copy to clipboard operation
efcore.pg copied to clipboard

HasPostgresArrayConversion cannot map an array nested inside value object

Open samisq opened this issue 4 years ago • 1 comments

HasPostgresArrayConversion cannot map an array that's nested inside a simple value object, because it expects the array property to be accessed directly from the entity.

For example, consider the model below:

public class TestEntity
{
    public TestEntity(Guid id, IntSequence sequence)
    {
        Id = id;
        Sequence = sequence;
    }
    public Guid Id { get; }
    public IntSequence Sequence { get; }
}
public class IntWrapper
{
    public int Value { get; }
    public IntWrapper(int value) => Value = value;
}
public class IntSequence
{
    public IntWrapper[] Values { get; }
    public IntSequence(IntWrapper[] values) => Values = values;
}

Previously, we could accomplish this with HasConversion, like:

modelBuilder.Entity<TestEntity>()
            .Property(x => x.Sequence)
            .HasConversion(x => x.Values.Select(v => v.Value).ToArray(),
                v => new IntSequence(v.Select(w => new IntWrapper(w)).ToArray()));

In domain-driven design, it's common to encapsulate primitives into value objects to create rich domain model that handles domain validation, and other business rules. Is there a recommended way to address this in v6?

samisq avatar Nov 08 '21 19:11 samisq

@samisq ValueObjects should use the OwnsOne, OwnsMany, or direct conversion to a literal pattern.

In your case it should be:

        modelBuilder.Entity<TestEntity>().OwnsOne(x => x.Sequence, builder =>
        {
            builder.Property(x => x.Values)
                .HasPostgresArrayConversion<IntWrapper, int>(x => x.Value, i => new IntWrapper(i));
        });

Blackclaws avatar Feb 04 '23 15:02 Blackclaws