Map string column in Entity Framework to Enum

26,788

Solution 1

It is ugly, but for mapping enums to strings I found something like this:

public virtual string StatusString
{
    get { return Status.ToString(); }
    set { OrderStatus newValue; 
          if (Enum.TryParse(value, out newValue))
          { Status = newValue; }
        }
}

public virtual OrderStatus Status { get; set; } 

OrderStatus is the enumerator type, Status is the enumerator and StatusString is the string version of it.

Solution 2

Probably a nicer version.

OrderStateIdentifier field is used for both JSON serialization and database field, while OrderState is only used in the code for convenience.

    public string OrderStateIdentifier
    {
        get { return OrderState.ToString(); }
        set { OrderState = value.ToEnum<OrderState>(); }
    }

    [NotMapped]
    [JsonIgnore]
    public OrderState OrderState { get; set; }


public static class EnumHelper
{
    /// <summary>
    /// Converts string to enum value (opposite to Enum.ToString()).
    /// </summary>
    /// <typeparam name="T">Type of the enum to convert the string into.</typeparam>
    /// <param name="s">string to convert to enum value.</param>
    public static T ToEnum<T>(this string s) where T: struct
    {
        T newValue;
        return Enum.TryParse(s, out newValue) ? newValue : default(T);
    }
}

Solution 3

You can do either:

Decorate the Enum property in your class as a text column

[Column(TypeName = "nvarchar(50)")]
public FileTypes FileType { get; set; }

OR

in your DatabaseContext class, override the OnModelCreating and add:

modelBuilder
  .Entity<File>()
  .Property(e => e.FileType)
  .HasConversion(new EnumToStringConverter<FileTypes>());

Solution 4

An alternative is to use a static class with string const fields instead of enums.

For example:

public class PocoEntity
{
    public string Status { get; set; }
}

public static class PocoEntityStatus
{
    public const string Ok = "ok";
    public const string Failed = "failed";
}

For added validation on the database side you can add a check constraint to verify that the column is the expected value (you can do this when mapping to an enum as well, but since the property is just a string this helps ensure the consumer of your api set the value properly).

ALTER TABLE [PocoEntity]
    ADD CONSTRAINT [CHK_PocoEntity_Status]
    CHECK ([Status] in ('ok', 'failed'));

Solution 5

I had the same problem. I've come up with a solution, but I'm not completely happy with it.

My Person class has a Gender enum, and I use data annotations to map the string to the database and ignore the enum.

public class Person
{
    public int PersonID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    [Column("Gender")]
    public string GenderString
    {
        get { return Gender.ToString(); }
        private set { Gender = EnumExtensions.ParseEnum<Gender>(value); }
    }

    [NotMapped]
    public Gender Gender { get; set; }
}

here is the extension method to get the correct enum from the string.

public class EnumExtensions
{
    public static T ParseEnum<T>(string value)
    {
        return (T)Enum.Parse(typeof(T), value, true);
    }
}

I wrote a blog post about this - http://nodogmablog.bryanhogan.net/2014/11/saving-enums-as-strings-with-entity-framework/

Share:
26,788
Sheldon Warkentin
Author by

Sheldon Warkentin

Experienced Software Engineer with a demonstrated history of working in various industries. Strong engineering professional skilled in Java, C#, .NET, AWS, Google Cloud, Kubernetes, Terraform, Docker, Project planning, architecture, Eclipse RCP, Visual Studio, and more!

Updated on July 23, 2022

Comments

  • Sheldon Warkentin
    Sheldon Warkentin almost 2 years

    Is there a way to map a string column to an enum in an Entity Model?

    I have done this in Hibernate, but can't figure it out in EMF.