2009-06-23 77 views
2

我問了一個previous question關於使用LinqToSql映射表上的枚舉值,答案是使用O/R設計器將類型設置爲global :: MyNamespace.TMyEnum。如何使用LinqToSql將字符串值隱式轉換爲枚舉?

如果您的枚舉基於整數,那麼工作正常。但是,如果你的枚舉基於字符串值呢?這方面最明顯的應用是:

public enum TGender { 
    Male, 
    Female, 
    Unknown, 
} 

在數據庫中的相應值是MFU。您無法將枚舉類型輸入爲字符串,那麼如何讓LinqToSql對象的Gender屬性返回TGender值?

回答

4

我一個getter屬性,以我的LINQ添加到SQL對象,它看起來是這樣的:

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

這會導致 「男性」。

+0

好的......但你如何讓Linq自動投出「M」給TGender.Male,「F」給TGender.Female等?我不想爲「DbGender」(字符串)和「性別」(TGender)分別設置屬性 - 字符串屬性根本沒有用處,我也不想用不必要的接口來污染我的代碼。 – 2009-06-23 16:26:11

1

允許我建議走行爲類的路線而不是枚舉。您將完全消除開關語句,並有能力逐項關聯元數據和行爲。

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

您還可以通過簡單地問自己希望得到的信息的性別對象應用於特定性別的行爲。例如,得克薩斯州的合法結婚年齡與性別有關。

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