EF 4.1 Code First - map enum wrapper as complex type

后端 未结 4 1241
误落风尘
误落风尘 2020-12-24 08:25

I\'m trying to build a generic solution to the problem of enums with EF 4.1. My solution is basically a generic version of How to fake enums in ef 4. The enum wrapper class

相关标签:
4条回答
  • 2020-12-24 09:19

    I got Nathan generic enum wrapper class to work by simply making it abstract and move:

    public static implicit operator EnumWrapper <TEnum> (TEnum e)
    

    to the derived classes like this:

    public class CategorySortWrapper : EnumWrapper<CategorySort>
    {
        public static implicit operator CategorySortWrapper(CategorySort e)
        {
            return new CategorySortWrapper() { Enum = e };
        }
    }
    
    public abstract class EnumWrapper<TEnum> where TEnum : struct, IConvertible
    {
        public EnumWrapper()
        {
            if (!typeof(TEnum).IsEnum)
                throw new ArgumentException("Not an enum");
        }
    
        public TEnum Enum { get; set; }
    
        public int Value
        {
            get { return Convert.ToInt32(Enum); }
            set { Enum = (TEnum)(object)value; }
        }
    
        public static implicit operator int(EnumWrapper<TEnum> w)
        {
            if (w == null)
                return Convert.ToInt32(default(TEnum));
            else
                return w.Value;
        }
    }
    

    in my code I just using the it like this

    public CategorySortWrapper ChildSortType { get; set; }
    
    category.ChildSortType = CategorySort.AlphabeticOrder;
    

    I didn't do anything else and EF 4.1 created a "ComplexType like field" in the database named ChildSortType_Value

    0 讨论(0)
  • 2020-12-24 09:21

    There's a much simpler way to map enums in EF 4: just create an int property on your ChickenSandwich class to represent the int value of the enum. That's the property that EF should map, then have a "mini wrapper" property to allow you to use the enum

    public class ChickenSandwich 
    {   
        public int ID { get; set; }
        public string Name { get; set; }
    
        // This property will be mapped
        public int CheeseColorValue { get; set; }
    
        public Color CheseColor
        {
            get { return (Color) CheeseColorValue; }
            set { CheeseColorValue = (int) value; }
        }
    }
    

    I actually don't have to use the Fluent API or any kind of attribute decoration for this to work. On generating the database, EF will happily ignore any type it doesn't know how to map, but the int property will be mapped.

    I have tried mapping enums based on that article too, but it caused me no end of headaches. This method works well, and you could adapt your solution to use your wrapper as the "mapping" property, i.e. CheeseColor in this case.

    0 讨论(0)
  • 2020-12-24 09:22

    That might be the best option for enums, but another idea would be to just use constants instead of enums:

    static void Main(string[] args)
    {
        Console.WriteLine("There are {0} red chicken sandwiches.", 
            sandwiches.ChickenSandwiches
                      .Where(s => s.Color == Color.red)
                      .ToArray().Length);
    }
    
    public struct Color
    {
        public const int red = 1;
        public const int green = 2;
    }
    
    public class ChickenSandwich
    {
        public ChickenSandwich()
        {
        }
    
        public int ID { get; set; }
        public string Name { get; set; }
        public int Color { get; set; }
    }
    
    public class Sandwiches : DbContext
    {
        public DbSet<ChickenSandwich> ChickenSandwiches { get; set; }
    }
    
    0 讨论(0)
  • 2020-12-24 09:24

    based on Henrik Stenbæk answer. assigning is working fine

    category.ChildSortType = CategorySort.AlphabeticOrder
    

    but comparing the wrapper to its enum doesn't work.

    if(category.ChildSortType == CategorySort.AlphabeticOrder)
    {
    
    }
    

    the following operator should be added to the abstract class

    public static implicit operator TEnum(EnumWrapper<TEnum> w)
            {
                if (w == null)
                    return default(TEnum);
                else
                    return w.EnumVal;
            }
    
    0 讨论(0)
提交回复
热议问题