对包含Entity Framework的字段使用枚举,但使用ToString值而不是整数

时间:2013-12-16 20:52:20

标签: c# entity-framework enumeration

我的数据库的字符串值受限于一组固定的值,如:

REGISTERED
PENDING
BANNED

目前我使用常量来表示这些值,但我宁愿使用enum

我使用的是EF 6,我认为它支持enum,但是我可以使用枚举并将它作为字符串表示形式保存到数据库中吗?

public enum RegistrationStatus
{
    REGISTERED,
    BANNED,
    PENDING
}

2 个答案:

答案 0 :(得分:3)

我很抱歉这将是如此多的代码,但你可以创建一个基于字符串的类型安全枚举,并证明它工作的唯一方法是提供一个工作示例。

班级

public sealed class Frequency : IEnumeration, IComparable

我们在POCO中声明为

public Frequency chargeFrequency { get; set; }

在地图文件中就是这样 - 请注意我们映射到value类的Frequency属性

this.Property(t => t.chargeFrequency.Value)
    .HasColumnName("chargeFrequency")
    .HasColumnType("varchar")
    .IsOptional()
    .HasMaxLength(25);

这是一种享受。

x.chargeFrequency = Frequency.Annually

唯一的缺点是intellisense无法为我们解决这个问题。

班级的静态部分

private static readonly Dictionary<string, Frequency> _list = 
    new Dictionary<string, Frequency>();

public static bool Contains(string key)
{
    return _list.Any(x => x.Key == key);
}

public static bool operator !=(Frequency a, Frequency b)
{
    return (!a.Equals(b));
}

public static bool operator ==(Frequency a, Frequency b)
{
    return (a.Equals(b));
}

public static implicit operator Frequency(string value)
{
    if (value == null || value.Trim().Length == 0) return Frequency.Null;
    if (Contains(value))
        return _list[value];
    else
        throw new InvalidCastException(string.Format("Frequency.{0} not found.", value));
}

public static implicit operator String(Frequency item)
{
    return item.Value;
}

public static readonly Frequency Null = new Frequency("");
public static readonly Frequency Annually = new Frequency("Annually");
public static readonly Frequency Fortnightly = new Frequency("Fortnightly");
public static readonly Frequency FourWeekly = new Frequency("FourWeekly");
public static readonly Frequency HalfYearly = new Frequency("HalfYearly");
public static readonly Frequency Monthly = new Frequency("Monthly");
public static readonly Frequency Quarterly = new Frequency("Quarterly");

班级的实例部分

private readonly string _value;
private readonly bool _readonly;
private Frequency _instance;

private Frequency(string value)
{
    _readonly = true;
    _value = value;
    _instance = this;
    _list[value] = _instance;
}

public Frequency()
{
    _readonly = false;
    _instance = Frequency.Null;
}

[XmlText]
public string Value
{
    get
    {
        if (_instance == Frequency.Null) return null;
        return _instance._value;
    }
    set
    {
        if (_readonly)
            throw new InvalidOperationException("Cannot assign a value to an enumeration.");
        if (value == null) _instance = Frequency.Null;
        else
        {
            if (!_list.ContainsKey(value))
                throw new NullReferenceException(string.Format("Frequency.{0} not found.", value));
            _instance = _list[value];
        }
    }
}

public override string ToString()
{
    return Value;
}

public override bool Equals(object obj)
{
    if (obj == null) return false;

    if (this.GetType() != obj.GetType()) return false;

    // safe because of the GetType check
    Frequency item = (Frequency)obj;

    return System.Object.ReferenceEquals(_instance, item);
}

public override int GetHashCode()
{
    if (_value == null) return "".GetHashCode();
    else return _value.GetHashCode();
}

public int CompareTo(object obj)
{
    if (obj is Frequency)
    {
        if (_value == null)
        {
            if (obj == null) return 0;
            else return -1;
        }
        Frequency compare = (Frequency)obj;
        return _instance.Value.CompareTo(compare.Value);
    }
    else
        throw new ArgumentException("Object is not a Frequency.");
}

答案 1 :(得分:0)

根据您对我评论的回复,以下是我的回答:

EF完全支持使用enum映射到自EF 5以来的数据库字段,但仅对int值执行此操作。考虑到您的数据库使用字符串,我建议您进行一些“间接映射”。我的意思是在您的对象(该枚举类型)上有一个NotMapped字段,当枚举更改时,该字段将使用字符串填充实际数据库字段。像这样:

public string RegistrationStatus { get; set; }

[NotMapped]
public RegistrationStatus EnumStatus
{
  get { return (RegistrationStatus) Enum.Parse(typeof(RegistrationStatus), this.RegistrationStatus); }
  set { this.RegistrationStatus = value.ToString();
}

通过执行此操作,您仍然可以将页面上的属性映射到此字段,并知道在更改时它将相应地更改基础string值。