3

This is my current EF Core model:

public class Application
{
    [Key]
    public string Name { get; set; }
    public HashSet<string> Fields { get; set; }
}

The hashset property doesn't work on its own, so I've added this in OnModelCreating:

modelBuilder.Entity<Application>()
     .Property(e => e.Fields)
     .HasConversion(
        v => v.ToArray(),
        v => new HashSet<string>(v));

That works in some cases, but there is a big issue with it.

When I insert an application initially, the hashset gets converted to a string array correctly, and the postgresql db driver stores it correctly.

However when I later get the application again, modify the hashset, and then call .SaveChanges(); it does not work!

I have to explicitly call ctx.Update(app); for the changes to get saved.

I think that is because the HashSet<string> instance does not change, only its content changes, so the change tracker won't be able to see any changes (but maybe I'm wrong about that reasoning).

How can I fix this?

The example here only has one HashSet, but other models will have many more properties that will all suffer from the same problem.

  • Is there any way to make the change tracker aware of those changes?
  • Is there maybe a way to implement a custom collection of some sort that will notify its "container" that it has been modified?
  • Is it maybe possible to tell EF to check the value after the conversion, instead of the hashset itself?
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Riki
  • 1,776
  • 1
  • 16
  • 31
  • tried to use [`ObservableHashSet`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.changetracking.observablehashset-1?view=efcore-3.0) instead of plain `HashSet`..? – Bagus Tesa Nov 12 '19 at 04:21
  • @BagusTesa Good idea! I replaced both occurrences of `HashSet` (where the prop is declared and where the conversion happens), but unfortunately it didn't help. Still no automatic change detection. – Riki Nov 12 '19 at 04:46
  • Does it work if you use `List` instead of `HashSet`? – mjwills Nov 12 '19 at 05:17
  • hi @Riki, just to be sure, you are not using `AsNoTracking` right? i do curious, why did microsoft said `ObservableHashSet` is a `HashSet` implemented that publish EF events but doesnt work in your case.. – Bagus Tesa Nov 12 '19 at 06:43
  • @mjwills Doesn't work with List either. – Riki Nov 13 '19 at 00:10
  • @BagusTesa Yeah, I'm not using AsNoTracking or similar anywhere in the project. – Riki Nov 13 '19 at 00:11

1 Answers1

0

Have you checked this: https://stackoverflow.com/a/20712012/11649486

Entity Framework does not support collections of primitive types. You can either create an entity (which will be saved to a different table) or do some string processing to save your list as a string and populate the list after the entity is materialized.

litetex
  • 193
  • 2
  • 8
  • It is worth noting that EF is moving towards supporting collections of primitive types. It's worth checking if it's now available. https://devblogs.microsoft.com/dotnet/announcing-ef8-preview-4/. It also can be done via Value converters now. https://learn.microsoft.com/en-us/ef/core/modeling/value-conversions?tabs=data-annotations – Jack Aug 16 '23 at 10:17