Dot-Net

EF 4.1 Code First - 將列舉包裝器映射為複雜類型

  • May 24, 2012

我正在嘗試為 EF 4.1 的列舉問題建構一個通用解決方案。我的解決方案基本上是How to fake enums in ef 4的通用版本。列舉包裝類在其餘程式碼中工作得非常好,並允許以下程式碼:

EnumWrapper<Color> c = Color.Red;

這是列舉包裝類:

public 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 TEnum(EnumWrapper<TEnum> w)
   {
       if (w == null) return default(TEnum);
       else return w.Enum;
   }

   public static implicit operator EnumWrapper<TEnum>(TEnum e)
   {
       return new EnumWrapper<TEnum>() { Enum = e };
   }

   public static implicit operator int(EnumWrapper<TEnum> w)
   {
       if (w == null)
           return Convert.ToInt32(default(TEnum));
       else
           return w.Value;
   }
}

列舉:

public enum Color { red = 1, green = 2, blue = 3 }

一點:

public class ChickenSandwich 
{
   public ChickenSandwich() {
       CheeseColor = new EnumWrapper<Color>();
   }

   public int ID { get; set; }
   public string Name { get; set; }
   public EnumWrapper<Color> CheeseColor { get; set; }
}

映射:

public class ColorMapping : ComplexTypeConfiguration<EnumWrapper<Color>> 
{
   public ColorMapping() {
       Ignore(x => x.Enum);
       Property(x => x.Value);
   }
}

我還嘗試將它映射到 ChickenSandwich 的 EntityTypeConfiguration 上,如下所示:

Property(x => x.CheeseColor.Value).HasColumnName("CheeseColor");

如果我將它留給 ColorMapping 並且不對 ChickenSandwichMapping 進行顯式映射,它只是不會將其放入數據庫中。如果我以 x.CheeseColor.Value 方式映射它,我會感到害怕:

System.InvalidOperationException:配置的屬性“CheeseColor”不是實體“ChickenSandwich”上的聲明屬性。驗證它沒有被明確地從模型中排除,並且它是一個有效的原始屬性。


編輯

我無法讓列舉包裝器的通用版本工作,所以我已經編寫了單獨的包裝器。這不是我想要的,因為它違反了DRY原則,但它確實允許我將列作為列舉進行查詢。

[ComplexType]
public class ColorWrapper
{
   [NotMapped]
   public Color Enum { get; set; }

   public int Value
   {
       get { return (int)Enum; }
       set { Enum = (Color)value; }
   }

   public static implicit operator Color(ColorWrapper w)
   {
       if (w == null) return default(Color);

       return w.Enum;
   }

   public static implicit operator ColorWrapper(Color c)
   {
       return new ColorWrapper { Enum = c };
   }
}

我不得不在 ChickenSandwich 類上使用 ColorWrapper。它或多或少透明地工作。然後必須將其添加到我的映射類建構子中以獲得我想要的列名:

Property(x => x.CheeseColor.Value).HasColumnName("CheeseColorId");

在 EF 4 中有一種更簡單的映射方法enums:只需在您的類上創建一個int屬性ChickenSandwich來表示列舉的 int 值。這是 EF 應該映射的屬性,然後有一個“迷你包裝器”屬性允許您使用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; }
   }
}

實際上,我不必使用 Fluent API 或任何類型的屬性修飾來實現這一點。在生成數據庫時,EF 會很高興地忽略它不知道如何映射的任何類型,但int會映射屬性。

我也嘗試過enums根據那篇文章進行映射,但這讓我頭疼不已。這種方法效果很好,您可以調整您的解決方案以使用您的包裝器作為“映射”屬性,即CheeseColor在這種情況下。

引用自:https://stackoverflow.com/questions/5667473