EF 4.1代码第一 - 映射枚举包装器作为复杂类型 [英] EF 4.1 Code First - map enum wrapper as complex type

查看:141
本文介绍了EF 4.1代码第一 - 映射枚举包装器作为复杂类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为EF 4.1创建枚举问题的一般解决方案。我的解决方案基本上是一个通用版本的如何在ef中伪造枚举4 。枚举包装类在其余的代码中令人惊奇地工作,并允许代码如下:

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 works wonderfully in the rest of the code and allows code like:

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 }

POCO:

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这样:

I've also tried mapping it on the ChickenSandwich's EntityTypeConfiguration like this:

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

如果我把它放在ColorMapping上,在ChickenSandwichMapping上没有明确的映射,把它放在数据库中。如果我将它映射到x.CheeseColor.Value方法,我会感到恐惧:

If I leave it up to the ColorMapping and do no explicit mapping on the ChickenSandwichMapping, it just doesn't put it in the database. If I map it the x.CheeseColor.Value way, I get the dreaded:


System.InvalidOperationException:
配置的属性'CheeseColor'是
不是实体
'ChickenSandwich'上声明的属性。验证它是否已从
模型中明确排除
,并且它是一个有效的基元
属性。

System.InvalidOperationException: The configured property 'CheeseColor' is not a declared property on the entity 'ChickenSandwich'. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property..






修改

我无法获得通用版本的枚举包装工作,所以我已经写了单独的包装纸。这不是我想要的,因为它违反了 DRY 原则,但它允许我将列查询为枚举。

I wasn't able to get the generic version of the enum wrapper working, so I've gone with writing individual wrappers. It's not exactly what I wanted because it violates the DRY principle, but it does allow me to query the column as an enum.

[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。它或多或少透明地工作。然后不得不将其添加到我的映射类构造函数中以获取我想要的列名称:

I had to use the ColorWrapper on the ChickenSandwich class. It works more or less transparently. Then had to add this to my mapping class constructor to get the column name I wanted:

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


推荐答案

有一个简单的方法来映射<$ c $在EF 4中的c>枚举:只需在您的 ChickenSandwich 类中创建一个 int 表示枚举的int值。这是EF应该映射的财产,然后有一个迷你包装属性,以允许您使用枚举

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; }
    }
}

我其实不用使用流利API或任何种类的属性装饰,使其工作。在生成数据库时,EF会高兴地忽略它不知道如何映射的任何类型,但 int 属性将被映射。

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.

我已经尝试过基于该文章映射枚举,但是它使我没有头痛的结局。这种方法运行良好,您可以调整您的解决方案,使用您的包装器作为映射属性,即 CheeseColor 在这种情况下。

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.

这篇关于EF 4.1代码第一 - 映射枚举包装器作为复杂类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆