none
EF and Enums RRS feed

  • Question

  • I see that EF 4.1 allows Enums to be mapped to the database as an integer, but this is not my question. 

    My question is that I want to save the enum string value to a field in the database. 

    I have an enum:


    public enum CodeSegmentTypes
    {
        Fund, SubObject, Generic
    }

    I want to store "Fund", "SubObject", and "Generic" to a field in the database. 


    So I have the class:

    public class CodeSegment : ModelBase
    {
        private Guid _CodeSegment_Id;

        private string _Code = String.Empty;
        private string _Name = String.Empty;
        private string _SegmentType = String.Empty;

        [Key]
        public Guid CodeSegment_Id { get { return _CodeSegment_Id; } set { _CodeSegment_Id = value; } }

        [Required]
        public string Code { get { return _Code; } set { _Code = value; } }
        [Required]
        public string Name { get { return _Name; } set { _Name = value; } }


        /// <summary>
        /// Do not set this value directly.  Set by the CodeSgmentType Property instead.
        /// </summary>
        ///
        [Required]
        public string SegmentType { get { return _SegmentType; } set { _SegmentType = value; } }

        [NotMapped]
        public CodeSegmentTypes CodeSegmentType
        {
            get
            {
                CodeSegmentTypes result = CodeSegmentTypes.Generic;
                if (!Enum.TryParse<CodeSegmentTypes>(_SegmentType, true, out result))
                {
                    throw new Exception("Unable to Parse CodeSegmentType of " + _SegmentType);
                }

                return (CodeSegmentTypes)result;
            }
            set
            {
                _SegmentType = value.ToString();
            }
        }
    }


    As you can see from the comments, I don't want the SegmentType set directly, rather use the CodeSegmentType property.  Of course, I could just make the _SegmentType property an enum, then change the corresponsing field in the database to int, but I would rather keep the field in the database a nvarchar field.  I know this makes the DBA contingnet cringe, but it really simplifies reporting and searching later on. 

    Marcel Roma pointed me to the following article (http://edo-van-asseldonk.blogspot.de/2012/03/readonly-collections-with-entity.html) to solve a similar issue, but I was not successful with this apporoach for a string property.  I also tried using a complex object, but was not able to get that to work either.  Any ideas?


    Bill Behning


    • Edited by WRBehning Tuesday, May 1, 2012 2:48 PM
    Tuesday, May 1, 2012 2:47 PM

Answers

  • Hi WRBehning,

    Welcome to MSDN Forum.

    You can write the code as below.

    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                using (myContext context = new myContext())
                {
                    CodeSegment cs = new CodeSegment();
                    cs.CodeSegment_Id = new Guid();
                    cs.Code = "code";
                    cs.Name = "name";
                    cs.SegmentType = CodeSegmentTypes.SubObject.ToString();
                    context.codeSegmentSet.Add(cs);
                    context.SaveChanges();
                }
            }
        }
    
        public enum CodeSegmentTypes
        {
            Fund, SubObject, Generic
        }
    
        public class CodeSegment 
        {
            private Guid _CodeSegment_Id;
    
            private string _Code = String.Empty;
            private string _Name = String.Empty;
            private string _SegmentType = String.Empty;
    
            [Key]
            public Guid CodeSegment_Id { get { return _CodeSegment_Id; } set { _CodeSegment_Id = value; } }
    
            [Required]
            public string Code { get { return _Code; } set { _Code = value; } }
            [Required]
            public string Name { get { return _Name; } set { _Name = value; } }
    
            public string SegmentType
            {
                get {
                    return _SegmentType;
                }
    
                set
                {
                    if(value==CodeSegmentTypes.Fund.ToString()||value==CodeSegmentTypes.Generic.ToString()||value==CodeSegmentTypes.SubObject.ToString())
                    {
                        _SegmentType=value;
                    }
                    else
                    {
                        //...
                        Console.Write("wrong value");
                        Console.ReadLine();
                    }
                }
            }
    
            /// <summary>
            /// Do not set this value directly.  Set by the CodeSgmentType Property instead.
            /// </summary>
            /// 
            //[Required]
            //public string SegmentType { get { return _SegmentType; } set { _SegmentType = value; } }
    
            //[NotMapped]
            //public CodeSegmentTypes CodeSegmentType
            //{
            //    get
            //    {
            //        CodeSegmentTypes result = CodeSegmentTypes.Generic;
            //        if (!Enum.TryParse<CodeSegmentTypes>(_SegmentType, true, out result))
            //        {
            //            throw new Exception("Unable to Parse CodeSegmentType of " + _SegmentType);
            //        }
    
            //        return (CodeSegmentTypes)result;
            //    }
            //    set
            //    {
            //        _SegmentType = value.ToString();
            //    }
            //}
        }
    
        class myContext : DbContext
        {
            public DbSet<CodeSegment> codeSegmentSet { get; set; }
        }
    }

    Best Regards

    Allen Li [MSFT]
    MSDN Community Support | Feedback to us

    Wednesday, May 2, 2012 3:28 AM
    Moderator

  • if(value==CodeSegmentTypes.Fund.ToString()||value==CodeSegmentTypes.Generic.ToString()||value==CodeSegmentTypes.SubObject.ToString())

    Should be written as follows:

    if (Enum.IsDefined(typeof(CodeSegmentTypes), value))
      _SegmentType = value;
    else
      ;//report error
      

    Anyway, as I already said, I think storing enums in a string literal (especially Flags enums) is evil and should really be avoided if possible.

    The performance impact of storing and searching varchars instead of ints is also very high, and doesn't worth it.


    Shimmy


    Wednesday, May 2, 2012 10:48 AM

All replies

  • Why on earth would you wanna do that!?

    What you should do is create a Flags enum, then store the numeric value in the database, here as an example:

    [Flags]
    enum MyOptions
    {
      Dog = 0x1,
      Cat = 0x2,
      Animals = Dog | Cat, //3
      Snake = 0x4,
      Lizard = 0x8,
      Reptiles = Snake | Reptile //12  
      Male = 0x10,
      Female = 0x20,
      FemaleDog = Dog | Female
    }

    Check out this for more info.


    Shimmy


    Wednesday, May 2, 2012 1:59 AM
  • Hi WRBehning,

    Welcome to MSDN Forum.

    You can write the code as below.

    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                using (myContext context = new myContext())
                {
                    CodeSegment cs = new CodeSegment();
                    cs.CodeSegment_Id = new Guid();
                    cs.Code = "code";
                    cs.Name = "name";
                    cs.SegmentType = CodeSegmentTypes.SubObject.ToString();
                    context.codeSegmentSet.Add(cs);
                    context.SaveChanges();
                }
            }
        }
    
        public enum CodeSegmentTypes
        {
            Fund, SubObject, Generic
        }
    
        public class CodeSegment 
        {
            private Guid _CodeSegment_Id;
    
            private string _Code = String.Empty;
            private string _Name = String.Empty;
            private string _SegmentType = String.Empty;
    
            [Key]
            public Guid CodeSegment_Id { get { return _CodeSegment_Id; } set { _CodeSegment_Id = value; } }
    
            [Required]
            public string Code { get { return _Code; } set { _Code = value; } }
            [Required]
            public string Name { get { return _Name; } set { _Name = value; } }
    
            public string SegmentType
            {
                get {
                    return _SegmentType;
                }
    
                set
                {
                    if(value==CodeSegmentTypes.Fund.ToString()||value==CodeSegmentTypes.Generic.ToString()||value==CodeSegmentTypes.SubObject.ToString())
                    {
                        _SegmentType=value;
                    }
                    else
                    {
                        //...
                        Console.Write("wrong value");
                        Console.ReadLine();
                    }
                }
            }
    
            /// <summary>
            /// Do not set this value directly.  Set by the CodeSgmentType Property instead.
            /// </summary>
            /// 
            //[Required]
            //public string SegmentType { get { return _SegmentType; } set { _SegmentType = value; } }
    
            //[NotMapped]
            //public CodeSegmentTypes CodeSegmentType
            //{
            //    get
            //    {
            //        CodeSegmentTypes result = CodeSegmentTypes.Generic;
            //        if (!Enum.TryParse<CodeSegmentTypes>(_SegmentType, true, out result))
            //        {
            //            throw new Exception("Unable to Parse CodeSegmentType of " + _SegmentType);
            //        }
    
            //        return (CodeSegmentTypes)result;
            //    }
            //    set
            //    {
            //        _SegmentType = value.ToString();
            //    }
            //}
        }
    
        class myContext : DbContext
        {
            public DbSet<CodeSegment> codeSegmentSet { get; set; }
        }
    }

    Best Regards

    Allen Li [MSFT]
    MSDN Community Support | Feedback to us

    Wednesday, May 2, 2012 3:28 AM
    Moderator

  • if(value==CodeSegmentTypes.Fund.ToString()||value==CodeSegmentTypes.Generic.ToString()||value==CodeSegmentTypes.SubObject.ToString())

    Should be written as follows:

    if (Enum.IsDefined(typeof(CodeSegmentTypes), value))
      _SegmentType = value;
    else
      ;//report error
      

    Anyway, as I already said, I think storing enums in a string literal (especially Flags enums) is evil and should really be avoided if possible.

    The performance impact of storing and searching varchars instead of ints is also very high, and doesn't worth it.


    Shimmy


    Wednesday, May 2, 2012 10:48 AM