如何使用LinqToSql隐式地将字符串值转换为枚举?

时间:2009-06-23 15:56:26

标签: c# linq linq-to-sql enums or-designer

我问了previous question关于使用LinqToSql在表上映射枚举值的问题,答案是使用O / R设计器将类型设置为global :: MyNamespace.TMyEnum。

如果您的枚举基于整数,则可以正常工作。但是如果你的枚举是基于字符串值怎么办?最明显的应用是:

public enum TGender {
  Male,
  Female,
  Unknown,
}

数据库中的等效值为MFU。您不能将枚举键入为字符串,那么如何使LinqToSql对象的Gender属性返回TGender值?

2 个答案:

答案 0 :(得分:4)

我将为我的LINQ to SQL对象添加一个getter属性,如下所示:

public TGender Gender
{
   switch(this.DbGender)
   {
      case "M":
        return TGender.Male;
   }
}

或者,如果您不想使用巨大的switch语句,则可以向枚举添加一个属性,该属性具有一个字符串属性,该属性表示数据库中该值的字符串值。然后,使用反射,获取正确的枚举,并返回。

以下是使用反射和属性执行此操作的示例:

public class EnumAttribute : Attribute
{
    public string DbValue
    {
        get;
        set;
    }
}

public enum TGender
{
    [EnumAttribute(DbValue = "M")]
    Male,
    [EnumAttribute(DbValue = "F")]
    Female,
    [EnumAttribute(DbValue = "U")]
    Unknown
}

    public TGender GetEnumValue(string s)
    {
        foreach (TGender item in Enum.GetValues(typeof(TGender)))
        {
            FieldInfo info = typeof(TGender).GetField(item.ToString());
            var attribs = info.GetCustomAttributes(typeof(EnumAttribute), false);
            if (attribs.Length > 0)
            {
                EnumAttribute a = attribs[0] as EnumAttribute;
                if (s == a.DbValue)
                {
                    return item;
                }
            }
        }

        throw new ArgumentException("Invalid string value.");
    }

测试一下:

var item = GetEnumValue("M");
Console.WriteLine(item);

这导致“男性”。

答案 1 :(得分:1)

请允许我建议使用行为类而不是枚举。您将完全消除switch语句,并能够逐项关联元数据和行为。

public class Gender
{
    private static readonly Dictionary<string, Gender> _items = new Dictionary<string, Gender>();

    public static readonly Gender Male = new Gender("M", "he", age => age >= 14);
    public static readonly Gender Female = new Gender("F", "she", age => age >= 13);
    public static readonly Gender Unknown = new Gender("U", "he/she", age => null);

    public string DatabaseKey { get; private set; }
    public string Pronoun { get; private set; }
    public Func<int, bool?> CanGetMarriedInTexas { get; set; }

    private Gender(string databaseKey, string pronoun, Func<int,bool?> canGetMarriedInTexas)
    {
        DatabaseKey = databaseKey;
        Pronoun = pronoun;
        CanGetMarriedInTexas = canGetMarriedInTexas;
        _items.Add(databaseKey, this);
    }

    public static Gender GetForDatabaseKey(string databaseKey)
    {
        if (databaseKey == null)
        {
            return Unknown;
        }
        Gender gender;
        if (!_items.TryGetValue(databaseKey, out gender))
        {
            return Unknown;
        }
        return gender;
    }

    public IEnumerable<Gender> All()
    {
        return _items.Values;
    }
}

而不是使用开关来获取数据库密钥,您只需要它:

public void MapViewToPerson(IEditPersonInfoView view, Person person)
{
    person.Gender = view.Gender.DatabaseKey;
    // ...
}

您还可以通过向Gender对象询问所需信息来应用性别特定行为。例如,德克萨斯州的合法婚姻同意年龄是针对性别的。

public void MapPersonToView(IEditPersonInfoView view, Person person)
{
    Gender gender = Gender.GetForDatabaseKey(person.Gender);
    view.Gender = gender;
    view.ShowMarriageSection = gender.CanGetMarriedInTexas(person.AgeInYears) ?? true;
    // ...
}