如何使用 LinqToSql 将字符串值隐式转换为枚举?
Posted
技术标签:
【中文标题】如何使用 LinqToSql 将字符串值隐式转换为枚举?【英文标题】:How do you implicitly convert a string value to an enumeration using LinqToSql? 【发布时间】:2009-06-23 15:56:26 【问题描述】:我向previous question 询问了有关使用 LinqToSql 在表上映射枚举值的问题,答案是使用 O/R 设计器将类型设置为 global::MyNamespace.TMyEnum。
如果您的枚举是基于整数的,那可以正常工作。但是如果你的枚举是基于一个字符串值呢?最明显的应用是:
public enum TGender
Male,
Female,
Unknown,
其中数据库上的等效值为M
、F
和U
。您不能将枚举键入为字符串,那么如何使 LinqToSql 对象的 Gender
属性返回 TGender
值?
【问题讨论】:
【参考方案1】:我会在我的 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);
这导致“男性”。
【讨论】:
好的...但是如何让 Linq 自动将“M”投射到 TGender.Male,将“F”投射到 TGender.Female 等?我不想为“DbGender”(字符串)和“Gender”(TGender)设置单独的属性——字符串属性对我完全没有用,我不想用不必要的接口污染我的代码。 这种情况下是没有办法的。您能做的最好的事情就是将 DbGender 属性设置为内部属性,并将 Gender 公开。是的,这并不理想,但我认为没有其他方法。【参考方案2】:请允许我建议走行为类而不是枚举的路线。您将完全消除 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;
// ...
【讨论】:
以上是关于如何使用 LinqToSql 将字符串值隐式转换为枚举?的主要内容,如果未能解决你的问题,请参考以下文章
1067:将 void 类型的值隐式强制转换为不相关的类型 Function