Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set a value comparer in ASP.NET Core 3.1

I have used "HasConversion" in my DBContext to define a JSonArray (Language/Value) and save it as a Text field for ages and It works like a charm, I added a new project to my solution, nothing changed but then I got a new error on adding migration regarding "setting a value comparer".

My Model is like:

    public class Brand
    {
        public int Id { get; set; }
        public new IList<LangValue> Name { get; set; } = new List<LangValue>();
    }

and DBContext is like:

    modelBuilder.Entity<Brand>(t =>
    {

        t.Property(p => p.Name).HasConversion(
            v => JsonConvert.SerializeObject(v, Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Include}),
            v => JsonConvert.DeserializeObject<IList<LangValue>>(v, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Include})
         );
    });

It was working perfectly, but after adding a new project I got Yellow error in adding migration and Model does not add to the new database.

Microsoft.EntityFrameworkCore.Model.Validation[10620] The property 'Name' on entity type 'Brand' is a collection or enumeration type with a value converter but with no value comparer. Set a value comparer to ensure the collection/enumeration elements are compared correctly.

like image 268
Mertez Avatar asked Jan 24 '20 04:01

Mertez


People also ask

What are value converters in EF?

Value converters allow property values to be converted when reading from or writing to the database.

Can we use Entity Framework 6 in asp net core?

To use Entity Framework 6, your project has to compile against . NET Framework, as Entity Framework 6 doesn't support . NET Core. If you need cross-platform features you will need to upgrade to Entity Framework Core.

What is IEntityTypeConfiguration?

IEntityTypeConfiguration<TEntity> InterfaceAllows configuration for an entity type to be factored into a separate class, rather than in-line in OnModelCreating(ModelBuilder).


1 Answers

The explanation from ValueComparer docs https://docs.microsoft.com/en-us/ef/core/modeling/value-comparers#mutable-classes

A typical value conversion on a list property might convert the list to and from JSON:

modelBuilder
    .Entity<EntityType>()
    .Property(e => e.MyProperty)
    .HasConversion(
        v => JsonSerializer.Serialize(v, null),
        v => JsonSerializer.Deserialize<List<int>>(v, null));

This then requires setting a ValueComparer<T> on the property to force EF Core use correct comparisons with this conversion:

var valueComparer = new ValueComparer<List<int>>(
    (c1, c2) => c1.SequenceEqual(c2),
    c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode())),
    c => c.ToList());

modelBuilder
    .Entity<EntityType>()
    .Property(e => e.MyProperty)
    .Metadata
    .SetValueComparer(valueComparer);
like image 118
Seagull Avatar answered Sep 22 '22 17:09

Seagull