Map string column in Entity Framework to Enum

前端 未结 8 1142
被撕碎了的回忆
被撕碎了的回忆 2021-02-18 13:46

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.

相关标签:
8条回答
  • 2021-02-18 14:21

    If you want to map the enum value to another correspondent string (ex. abbreviation) you can use this approach:

    public class MinhaClasse
    {
        public string CodTipoCampo { get; set; }
    
        [NotMapped]
        public TipoDado TipoCampo
        {
            get => DictValorTipoDado.SingleOrDefault(e => e.Value == CodTipoCampo).Key;
            set => CodTipoCampo = DictValorTipoDado[value];
        }
    
        private Dictionary<TipoDado, string> DictValorTipoDado = new Dictionary<TipoDado, string>()
        {
            { TipoDado.Texto, "T" },
            { TipoDado.Numerico, "N" },
            { TipoDado.Data, "D" }
        };
    
        public enum TipoDado { Texto, Numero, Data }
    }
    
    0 讨论(0)
  • 2021-02-18 14:23

    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);
        }
    }
    
    0 讨论(0)
  • Acutally I think there is another solution to this.

    What we did in our Project recently was using Extension Methods.

    I wrote two of them, one for the Enum and one for the Entity, but here is the Example:

    namespace Foo.Enums
    {
        [DataContract]
        public enum EAccountStatus
        { 
            [DataMember]
            Online,
            [DataMember]
            Offline,
            [DataMember]
            Pending
        }
    

    ... the enum itself, and now the extension methods containing static class:

        public static class AccountStatusExtensionMethods
        {
    
            /// <summary>
            /// Returns the Type as enumeration for the db entity
            /// </summary>
            /// <param name="entity">Entity for which to check the type</param>
            /// <returns>enum that represents the type</returns>
            public static EAccountStatus GetAccountStatus(this Account entity)
            {
                if (entity.AccountStatus.Equals(EAccountStatus.Offline))
                {
                    return EAccountStatus.Offline;
                }
                else if (entity.AccountStatus.Equals(EAccountStatus.Online))
                {
                    return EAccountStatus.Online;
                }
                else if (entity.AccountStatus.Equals(EAccountStatus.Pending))
                {
                    return EAccountStatus.Pending;
                }
                throw new System.Data.Entity.Validation.DbEntityValidationException(
                    "Unrecognized AccountStatus was set, this is FATAL!");
            }
    

    ... the extension method for the entity type, and a convenience method for shorter typing:

            /// <summary>
            /// Gets the String representation for this enums choosen 
            /// </summary>
            /// <param name="e">Instance of the enum chosen</param>
            /// <returns>Name of the chosen enum in String representation</returns>
            public static String GetName(this EAccountStatus e)
            {
                return Enum.GetName(typeof(EAccountStatus), e);
            }
        }
    }
    

    ... and finally usage:

    // to set always the same, mappable strings:
    db.AccountSet.Single(m => m.Id == 1).Status = EAccountStatus.Online.GetName();
    
    // to get the enum from the actual Entity you see:
    EAccountStatus actualStatus = db.AccountSet.Single(m => m.Id == 1).GetAccountStatus();
    

    Now, you just need to be "using Foo.Enums;" and you can call the methods on the entity as well as on the enum. And even better, in some sort of wrappers for your entities, you could also do seamless marshalling between defferent types representing the same thing in big projects.

    The only thing worth noting about this is that you sometimes have to execute the extension method before you hand your Linq expression to Linq. The problem here is that Linq can't execute the extension method in its own context...

    Maybe just an alternative, but we've done it like that because it gives you great flexibility on how to get things for entities. You could easily write an extension to receive an Accounts actual Products in ShoppingCart...

    Greetings, Kjellski

    0 讨论(0)
  • 2021-02-18 14:26

    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.

    0 讨论(0)
  • 2021-02-18 14:29

    It's on the roadmap for EF7: https://github.com/aspnet/EntityFramework/issues/242

    You may want to vote for it: http://data.uservoice.com/forums/72025-entity-framework-feature-suggestions/suggestions/2639292-simple-type-mapping-or-mapped-type-conversion-sup

    0 讨论(0)
  • 2021-02-18 14:30

    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'));
    
    0 讨论(0)
提交回复
热议问题