2015-09-12 9 views
11

としてデータベースに列挙型を保存するためにどのようにこれは、私たちがは、文字列

enter image description here

のIntで

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 
} 

現在、それが保存されたデータのゾンビや人間の可能性タイプを持っている私のモデルクラスであります

私は人間ではなくゾンビとしてデータを保存したいのですが、intではなく

+1

列挙型は静的オブジェクトなので、データベースに保存する必要はありません。実際にはデータベース内の項目を定義し、T4テンプレートを使用して列挙型でコードを生成する必要があります。 –

+4

列挙型の値_is_はintです。あなたは本当にそのように保存する必要があります。あなたはDBの文字列としてそれを持っている非常に良い理由がない限り..あなたはそうしないと思います。 –

+3

@ Pierre-LucPineault:intとして保存するのは危険ではないですか?すべての人が列挙型を並べ替えるだけでなく、すぐにデータベースのすべての値が間違った列挙型を指しているのではないでしょうか? – Diskdrive

答えて

3

私は私が覚えている限りでは、この問題を抱えていたし、正直私はなぜMSは、(NHが常に以来のようにそれを行うことができ、この機能を追加していないかわかりません。 )。私は通常のようにconstの文字列クラスを使用しなかったものを

どれかの方法、:

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

} 

短所 - などの簡単なようにすることができます。

ダウンサイド - 緩やかな型チェック(プログラムで強制することもできますが)。


今回は、もっと野心的なことを考えました。だから私はブライアン(いくつかの欠点があります。たとえば、与えられた列挙型がドメイン全体で広く使用されている)という概念を採用しました。

基本コンポーネントクラスが値を格納する:よく..私は、次の作業だ

[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はい拡張メソッドである - 'パブリック静的T ToEnum (この文字列値) {リターン(T)Enum.Parse(typeof演算(T)、値、TRUE)。 } ' –

3

文字列として保存するのは良い考えではありませんが、あなたのen灰色でef enum to lookupと非常に使いやすいです。

+2

嬉しいですね:-) も参照してください。http://stackoverflow.com/q/11167665/10245 –

+0

enumを 'nvarchar()'として保存するのは良い考えではないのですか?テキストはデータベースの整数よりも読みやすくありませんか? – Blaise

+0

柔軟性とパフォーマンス@Blaise – dotctor

1

私は、intとして保存するほうが、intをDBから非常に簡単にenumにキャストできます。

あなたが望むものなら、2つのアプローチがあります。 Type.Zombie.ToString()(またはそれぞれType.Human.ToString())をデータベース(「ゾンビ」)に保存するか、使用している値DescriptionAttributeを取得してDBに保存することができます。説明を得る方法はhereと記載されています。 - この場合も "ゾンビ"になりますが、それ以外の場合はDescription()で書くこともできます。

ToStringを使用すると、Enum.Parseを使用してenumのインスタンスを取得できます。説明を使用すると、簡単ではありません。

+1

Entity Frameworkは現在列挙型をサポートしており、int型をDBから列挙型の各値にキャストする必要はありません。 – dotctor

9

dbに列挙型として列挙を保存することができますが、私はそれが最良のアイデアではないことをdotctorに同意しますが、必要に応じていくつかの変更を加える必要があります。

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の両方を追跡するにはどうすればよいでしょうか?私は、レコードをフェッチするときにnull引数の例外が発生しています。 – TWilly

+1

[NotMapped]を削除し、OPの質問に対する唯一の実際の回答であるdb – Bryan

+1

の他の列に設定してみてください。 :) – toddmo