Conversion of EF Core collection to CSV or null

88 Views Asked by At

I have this entity property, which is stored in the database as a CSV or null:

public ICollection<string> Names { get; } = new List<string>();

I have this configuration:

modelBuilder
  .Entity<Person>()
  .Property(e => e.Names)
  .HasConversion(
    x => x.Any() ? string.Join(',', x) : null,                     // this works
    x => (x ?? "").Split(',', StringSplitOptions.None).ToList(),   // this fails
    new ValueComparer<ICollection<string>>(
      equalsExpression:   (c1, c2) => c1!.SequenceEqual(c2!),
      hashCodeExpression: c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode(StringComparison.Ordinal))),
      snapshotExpression: c => c.ToHashSet())
  .IsRequired(false);

That successfully translates an empty collection to a database NULL. But a database NULL is converted to a c# null instead of an empty collection.

Where is my mistake?

(I cannot change the property's nullability or remodel the database; both are outside my control.)

2

There are 2 best solutions below

2
On BEST ANSWER

According to the documentation: "A null value will never be passed to a value converter. A null in a database column is always a null in the entity instance, and vice-versa."

I guess the easiest solution is just mapping manually.

0
On

A workaround:

modelBuilder
  .Entity<Person>()
  .Property(e => e.Names)
  .HasConversion(
    x => x.Any() ? string.Join(',', x) : "",                           // changed
    x => x.Split(',', StringSplitOptions.RemoveEmptyEntries).ToList(), // changed
    new ValueComparer<ICollection<string>>(
      equalsExpression:   (c1, c2) => c1!.SequenceEqual(c2!),
      hashCodeExpression: c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode(StringComparison.Ordinal))),
      snapshotExpression: c => c.ToHashSet())
  .IsRequired();                                                       // changed

Unfortunately that converts an empty collection in code to an empty string "" in the database, instead of NULL.

If you want that behaviour, please upvote this repo issue.