Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The property 'PropertyName' could not be mapped, because it is of type 'List<decimal>'

I got this problem when I try to create the database with EntityFramework Core:

The property 'Rating.RatingScores' could not be mapped, because it is of type 'List' which is not a supported primitive type or a valid entity type. Either explicitly map this property, or ignore it using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.

Here is the class:

public class Rating
{
    public int Id { get; set; }

    public List<decimal> RatingScores { get; set; }

    public decimal Score
    {
        set => Score = value;
        get => Math.Round(RatingScores.Sum() / RatingScores.Count, 1);
    }
}
like image 906
Eduard Stefanescu Avatar asked Aug 02 '18 17:08

Eduard Stefanescu


3 Answers

If the Rating class has multiple RatingScores you have a one-to-many relationship and the RatingScores property needs its own table, you therefore need to create a new class.

Class RatingScore 
{
  public int Id { get; set; }
  public decimal RtSc { get; set; }
}

Then the Rating property will look like this:

public List<RatingScore> MyRatingScores { get; set; }

However if each Rating has one RatingScore, your property should not be a collection.

public RatingScore MyRatingScore { get; Set; }
like image 166
TuPack Avatar answered Nov 05 '22 22:11

TuPack


Ok. Here is my error and I just found what the problem is.

The property 'LogEntry.Timestamp' could not be mapped because it is of type 'Instant', which is not a supported primitive type or a valid entity type. Either explicitly map this property, or ignore it using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.

Actually its fairly clear what it is trying to say.

I have overridden OnModelCreating but I missed a trivial thing.

Here is my dbcontext class.

public class ExtendedElsaMigrationsDbContext : SqlServerContext
{
    public ExtendedElsaMigrationsDbContext(DbContextOptions options) : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // I should not comment out this base method call.
        // base.OnModelCreating(modelBuilder);
        // modelBuilder.Entity<User>();

        modelBuilder.ConfigureExtendedElsaDbContext();
    }
} 

Note that I had commented out the base method call. And that is what is causing the problem.

The overridden method should be as follows.

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        //    //modelBuilder.Entity<User>();

        modelBuilder.ConfigureExtendedElsaDbContext();
    }

Summary: Don't forget to call the base method when you are overriding a method. Many times base method don't do much, so we ignore them. But some times they do. So always call the base methods.

like image 43
VivekDev Avatar answered Nov 05 '22 23:11

VivekDev


When you really need to put multiple values in single column can use below way

Let's say you want to create only one table for below class

public class SomeClass
{
    public Guid ID { get; set; }
    public IEnumerable<int> Values { get; set; }
}

First create a converter, which will control .net values to db values and vice versa

    using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
 
    public class IntListToStringValueConverter : ValueConverter<IEnumerable<int>, string>
    {
        public IntListToStringValueConverter() : base(le => ListToString(le), (s => StringToList(s)))
        {

        }
        public static string ListToString(IEnumerable<int> value)
        {
            if (value==null || value.Count()==0)
            {
                return null;
            }
 
            return value.Join(',');
        }

        public static IEnumerable<int> StringToList(string value)
        {  
            if (value==null || value==string.Empty)
            {
                return null;
            }

            return value.Split(',').Select(i => Convert.ToInt32(i)); ; 
            
        }
    }

And DbContext should have below method

 protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
         .....

        var IntValueConverter = new IntListToStringValueConverter();

        modelBuilder
            .Entity<SomeClass>()
            .Property(e => e.Values)//Property
            .HasConversion(IntValueConverter);

    }

Done!! IT should work

like image 3
Moumit Avatar answered Nov 05 '22 22:11

Moumit