2016-05-25 2 views
3

typesafe enum patternをエンティティフレームワークコアrc2に実装するにはどうすればよいですか?エンティティフレームワークコアrc2で型保証されたenumパターンを実装する方法

public class TestStatus 
{ 
    [Column("Id")] 
    public int Id { get; private set; } 

    [Column("Description")] 
    public string Description { get; private set; } 

    [Column("LongDescription")] 
    public string LongDescription { get; private set; } 

    private TestStatus(int id 
     , string description 
     , string longDescription) 
    { 
     Id = id; 
     Description = description; 
     LongDescription = longDescription; 
    } 

    public TestStatus() { } 

    public static readonly TestStatus Active = new TestStatus(1, "Active", "Active Long Description"); 
    public static readonly TestStatus Pending = new TestStatus(2, "Pending", "Pending Long Description"); 
    public static readonly TestStatus Cancelled = new TestStatus(3, "Cancelled", "Cancelled Long Description"); 
} 

ID生成戦略はOnModelCreatingに設定されている:

builder.Entity<TestStatus>() 
    .Property(s => s.Id) 
    .ValueGeneratedNever(); 

これは単純化した例であるが、実際のコードがRC1で働いていました。 rc2にアップグレードするときに、プロパティをマップするようにColumn属性を追加する必要がありました(私はこれがプライベートセッターのためであると想定しています)。

var i = new TestItem 
{ 
    Name = "Test Item 2", 
    Status = TestStatus.Active 
}; 
_context.Items.Add(i); 
_context.SaveChanges(); 

私は、ユースケースに応じて、次のいずれかのエラーを取得:タイプセーフ列挙値を代入しようとしたとき

は例外InvalidOperationException:エンティティタイプ「TestStatus」のインスタンスは、別のインスタンスのために追跡することができません同じキーを持つこのタイプは既に追跡されています。新しいエンティティについては、IIdentityGeneratorを使用して一意のキー値を生成することを検討してください。

それとも

SqlExceptionが:PRIMARY KEY制約 'PK_Statuses' の違反。オブジェクト 'dbo.Statuses'に重複キーを挿入できません。重複キー値は(1)です。ステートメントは終了されました。

私はこのエラーを理解しています。 EFは同じIdで新しいインスタンスを作成しようとしていると考えています。これらのインスタンスを同じとみなす必要があることをEFにどのように伝えることができますか?私はtypesafe enumパターンから離れることでこれを回避することができます。可能であれば、パターンと一緒に動作させたいのです。それはrc1で働いていた。

+0

なぜ 'TestStatus'オブジェクトはすべて同じ' Id'を持っていますか? – noox

+0

@nooxそれはタイプミスでした。私はそれを修正するために質問を編集しました。ありがとう! –

答えて

2

タイプセーフパターンを使用しているため、オブジェクト全体を永続化する必要はありません。単にIDを格納し、そのようなラッパーの作成:私はIDとして文字列を使用しますが、あなたが好きなタイプを使用することができ、いくつかの理由から

[Required] 
    protected string ObjectTypeValue { get; set; } 

    [NotMapped] 
    public ObjectType Type 
    { 
     get { return ObjectType.Parse(ObjectTypeValue); } 
     set { ObjectTypeValue = value.Print(); } 
    } 

を。

+1

@samが提案していた答えの周りに私の頭を包むのに1〜2分かかりました。これに苦しんでいるかもしれない人にとっては、Type-Safe Enumを使用するタイプのプロパティを作成することです。タイプセーフなEnumは値(またはIDなど)を格納するだけです。そうすればEFは楽しいものになります。単純なタイプを保存するだけです。次に、あなたの列挙型で何らかの '.Parse'メソッドを呼び出すことによって、Type-Safe Enumをオブジェクトとして公開する「ラッパー」を作成します。タダ! – Greg

関連する問題