EF 4.1 Code First - 將列舉包裝器映射為複雜類型
我正在嘗試為 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 應該映射的屬性,然後有一個“迷你包裝器”屬性允許您使用enumpublic 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在這種情況下。