Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EF Core list of Enums

I'm working on small application with organizing hotel reservations in Entity Framework Core. I need to add information about number and the type of beds in every room. I was thinking and I decided that List of enums will be better, than storing it in separate table. But I don't know how to achieve it

public enum Bed
{
    Single = 1,
    Double = 2,
}

public class Room : IEntity
{
   [Key]
   public int Id { get; set; }
        
   public string RoomIdentifier { get; set; }
   public ICollection<Bed> Beds { get; set; }
        
   public int Floor { get; set; }
   public double Price { get; set; }

   public bool IsFree { get; set; }
   public bool IsOutOfService { get; set; }
   public bool ShouldBeCleaned { get; set; }
        
   public ICollection<RoomReservation> RoomReservations { get; set; }
}

Is it possible to do so? I was also thinking to save it as a string like (1,2,1,2) and then parse it to receive number and type of beds in room. Much thanks for help!

like image 732
Hesh Avatar asked Dec 16 '20 17:12

Hesh


2 Answers

Here is an example with Object names made up, hopefully it helps.

In OnModelCreating:

modelBuilder.Entity<Room>()
        .Property(e => e.BedList)
        .HasConversion(
            v => string.Join(',', v),
            v => v.Split(',', StringSplitOptions.RemoveEmptyEntries).ToList() ?? new List<Bed>())
        .Metadata.SetValueComparer(valueComparer);

You will have to create your own valuecomparer example below for a list:

var valueComparer = new ValueComparer<ICollection<string>>(
                    (c1, c2) => c1.SequenceEqual(c2),
                    c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode())),
                    c => (ICollection<string>)c.ToHashSet());
like image 159
Richard Hubley Avatar answered Nov 10 '22 07:11

Richard Hubley


I misread the question... if you're trying to store a comma-separate list in a single field, follow richard's example... or handle it manually in your mapping logic if you have one.

The below answer is only if you're trying to use a enum instead of having a table, not if you're trying to fit multiple enum values in a single column.


There's a nice C# package called SmartEnum by Ardalis Steve Smith. GitHub Link

It'll allow you to have a strongly typed enum, but you can save it in the database as a string or integer or however you please.

Here's an example:

public sealed class Bed : SmartEnum<TestEnum>
{
    // static instances of the SmartEnum Bed represents the enumerations
    public static readonly Bed Single = new Bed(name: "Single", value: 1, isPremium: false);
    public static readonly Bed Double = new Bed(name: "Double", value: 2, isPremium: true);


    // example additional property of each enumeration
    public bool IsPremium = false;


    private Bed(string name, int value, bool isPremium) : base(name, value)
    {
        IsPremium = isPremium;
    }
}

The above example, the enum is backed by an int value. You can have it backed by a string by using : SmartEnum<TestEnum, string>. It supports implicit casts, etc., works well with EF, and you'll be able to "list" enums as needed.

like image 41
galdin Avatar answered Nov 10 '22 06:11

galdin