web-dev-qa-db-ja.com

主キーエンティティフレームワークコードの最初の違反

私はC#から始めて、自分のDBを作りたかったのです。

私は2つのモデルを持っています

public class AModel 
{
    public Guid ID { get; private set; }
    public string Name { get; set; }
    public int Count { get; set; }
    public AModel()
    {
        this.ID = Guid.NewGuid();
    }
}

public class BModel 
{
    public Guid ID { get; private set; }
    public string Name { get; set; }
    public AModel Model { get; set; }
    public BModel()
    {
        this.ID = Guid.NewGuid();
    }
}

BModelをDBに保存しようとすると、次のエラーが発生します。

PRIMARYKEY制約「PK_dbo.AModels」への違反。オブジェクト 'dbo.AModels'に重複するキーを挿入できません。重複するキー値は(48ee1711-8da4-46c1-a714-19e985211fed)です。\ r\nステートメントは終了しました。

これで解決すると思いました

modelBuilder.Entity<BModel>().HasRequired(t => t.Model).WithMany();

しかし、私は完全に迷子になっているようです。誰かがこの簡単な例で私を助けてくれますか?

9
Tomas Bruckner

あなたのコメントは重要な情報を明らかにします。そのAModelをコンボボックスからBModelに追加すると、それまでにDbContextから切り離されます。次にそれをモデルに追加すると、EntityFrameworkは新しいオブジェクトがあると見なします。

IDはDatabaseGenerationOptions.Noneとして構成されているため、自分で指定した主キーが使用されます。あなたの場合、これは分離されたオブジェクトのPKです。したがって、EFがこのエントリを挿入しようとすると、そのキーを持つエンティティがすでに存在するため、上記の例外がスローされます。

これを解決する方法はいくつかあります。

  • 既存のエンティティを取得します

このエンティティは、取得時にコンテキストにアタッチされ、これを使用できるようになります。ただし、これは追加のルックアップを意味します。最初にそれらをコンボボックスに取得し、次にコンボボックス内のエンティティからIDを使用して、データベースから再度取得します。

使用例:

AModel Get(AModel detachedModel)
{
    using(var context = new MyContext())
    {
        return context.AModels.Single(x => x.ID == detachedModel.ID);
    }
}
  • 既存のモデルを添付します

これにより、Entity-Frameworkは、エンティティがデータベースにすでに存在していることを認識できるようになります。

using(var context = new MyContext())
{
    context.AModels.Attach(detachedModel);
}

アタッチする他の方法は、状態を未変更に設定することです。

context.Entry(detachedModel).State = EntityState.Unchanged;

または変更済み(値も変更した場合)

context.Entry(detachedModel).State = EntityState.Modified;
11
Jeroen Vannevel