2015-09-12 112 views
11

這是我的模型類,我們有一個類型可以是一個殭屍或人類如何在數據庫中保存枚舉作爲字符串

public class User 
{ 
    public int ID { get; set; } 
    public string Name { get; set; } 
    public Type Type { get; set; } 
    public List<Wepon> WeposInList { get; set; } 
    } 

public enum Type 
{ [Description("Zombie")] Zombie, 
    [Description("Human")] Human 
} 

在詮釋

enter image description here

目前,它保存數據

我想將數據保存爲Human和Zombie,而不是int

+1

枚舉是一個靜態對象,將它保存到數據庫沒有意義......真的,您應該定義數據庫中的項目,然後使用T4模板在代碼中生成枚舉。 –

+4

枚舉值_is_ int。你應該真的把它保存下來。除非你有一個很好的理由把它作爲DB中的一個字符串。我認爲你不這樣做。 –

+3

@ Pierre-LucPineault:將它作爲int存儲並不危險嗎?難道不是都有人需要做的是重新排列枚舉,然後立即在你的數據庫中的所有值指向了錯誤的枚舉沒有任何警告 – Diskdrive

回答

3

我記得我儘量有這個問題,老實說,我不知道爲什麼沒有MS添加這一功能(NH可以像一直以來。 )。

任何方式,我通常所做的是使用常量字符串類,如:

public static class MyEnum 
{ 
    public const string Foo = "Foo"; 
    public const string Bar = "Bar"; 
} 

public class Client 
{ 

    public string MyVal { get; set; } 

    public Client() 
    { 
     MyVal = MyEnum.Bar; 
    } 

} 

缺點 - 就這麼簡單就可以了。

下降 - 你鬆散的類型檢查(儘管它可以通過編程實現)。


所以這次我試着去想更有野心的事情。所以我採用了Brian所描述的概念(當某個枚舉在域中被廣泛使用時,它有一些缺點)。和好..我得到了以下工作:

基本組件類存儲的值:

[ComplexType] 
public class DbEnum<TEnum> 
{ 
    public string _ { get; set; } 

    public DbEnum() 
    { 
     _ = default(TEnum).ToString(); 
    } 

    protected DbEnum(TEnum value) 
    { 
     _ = value.ToString(); 
    } 

    public TEnum ToEnum() 
    { 
     return _.ToEnum<TEnum>(); 
    } 

    public static implicit operator DbEnum<TEnum>(TEnum value) 
    { 
     return new DbEnum<TEnum>(value); 
    } 

    public static implicit operator TEnum(DbEnum<TEnum> value) 
    { 
     return value.ToEnum(); 
    } 
} 

...這將足夠基本上除了.. EF不支持泛型類型.. 。

這意味着你必須有一些像每一個枚舉...

public enum PrivacyLevel 
{ 
    Public, 
    Friends, 
    Private 
} 

public class PrivacyLevelEnum : DbEnum<PrivacyLevel> 
{ 
    public PrivacyLevelEnum() : this(default (PrivacyLevel)) 
    {  
    } 

    public PrivacyLevelEnum(PrivacyLevel value) : base(value) 
    { 
    } 

    public static implicit operator PrivacyLevelEnum(PrivacyLevel value) 
    { 
     return new PrivacyLevelEnum(value); 
    } 

    public static implicit operator PrivacyLevel(PrivacyLevelEnum value) 
    { 
     return value.ToEnum(); 
    } 
} 

,讓你可能例如很容易產生一些鍋爐板使用T4模板。

並最終結束您使用:

public class CalendarEntry : Entity 
{ 

    public virtual PrivacyLevelEnum PrivacyLevel { get; set; } = new PrivacyLevelEnum(); 

} 

但既然你已經制定隱式轉換,類聲明是唯一要注意的幫手類型。

+0

這個方法發現在哪裏string.ToEnum (); - 它是一個擴展方法 – Ken

+0

@Ken是 - '公共靜態ŤToEnum (此字符串值) { 返回(T)Enum.Parse(typeof運算(T),值,TRUE); }' –

3

將它們存儲爲字符串不是一個好主意,但是您可以爲您的en創建查找表與ef enum to lookup,這是非常容易使用。

+2

很高興你喜歡它:-) 另請參見http://stackoverflow.com/q/11167665/10245 –

+0

你可以請解釋一下,爲什麼把numchar()存儲爲枚舉不是一個好主意?文本比數據庫中的整數更不可讀? – Blaise

+0

靈活性和性能@Blaise – dotctor

1

我覺得將它們存儲爲int會更有用,因爲您可以非常輕鬆地將int從DB轉換爲enum

但是,如果它你的願望,有兩種方法。您可以將Type.Zombie.ToString()(或分別爲Type.Human.ToString())保存到數據庫(將爲「Zombie」),或者您可以獲得您正在使用的值DescriptionAttribute並將其保存到數據庫。如何獲得描述描述here。 - 在這種情況下,它也將是「殭屍」,但它可能是您在Description()中編寫的任何其他內容。

如果您使用ToString,則可以使用Enum.Parse獲取enum的實例。如果你使用描述,那並不容易。

+1

實體框架現在支持枚舉,也沒有必要從DB鑄INT到它的枚舉相應數值。 – dotctor

9

您可以將枚舉保存爲數據庫作爲字符串,我同意點擊它不是最好的想法,但如果需要,您需要進行一些更改。

public class User 
{ 
    public int ID { get; set; } 
    public string Name { get; set; } 
    public List<Wepon> WeposInList { get; set; } 

    [Column("Type")] 
    public string TypeString 
    { 
     get { return Type.ToString(); } 
     private set { Type= value.ParseEnum<Type>(); } 
    } 

    [NotMapped] 
    public Type Type { get; set; } 
} 

將此擴展類添加到您的項目。

public static class StringExtensions 
{ 
    public static T ParseEnum<T>(this string value) 
    { 
     return (T)Enum.Parse(typeof(T), value, true); 
    } 
} 

全部細節在這裏 - http://NoDogmaBlog.bryanhogan.net/2014/11/saving-enums-as-strings-with-entity-framework/

+1

我將如何使用它來跟蹤數據庫中的標籤和ID?我在獲取記錄時收到空參數異常。 – TWilly

+1

嘗試刪除[NotMapped],它的分貝 – Bryan

+1

的唯一實際的答案OP的問題設置一些列。 :) – toddmo

相關問題