2015-10-19 9 views
6

Entity Framework 6とSQLiteデータベース(System.Data.SQLite.EF6)を使用していますが、同じ主キーでエントリを作成できませんそれを削除した直後。エンティティのEntity Framework 6とSQLite - 前に削除されたエントリのPKでエントリを作成できません

マイモデル::

public class Person 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.None)] 
    public int Id { get; set; } 

    public int Name { get; set; } 
} 

STEPS:たとえば

1)私は人々の私のテーブルにID = 1)と(このエンティティPERSON1のインスタンスを挿入します。

using (var context = new MyDbContext()) 
{ 
    context.Create(person1); 
    await context.SaveChangesAsync(); 
} 

2)Afters一部トメ私は全体者テーブルをクリア:私は第1段階からのエントリと同じ主キーを持つエントリを追加しよう

using (var context = new MyDbContext()) 
{ 
    await context.Database.ExecuteSqlCommandAsync(string.Format("DELETE FROM `PersonModels`")); 
    await context.SaveChangesAsync(); 
} 

3):= 1 idのPERSON2( )

using (var context = new MyDbContext()) 
{ 
    context.Create(person2); 
    await context.SaveChangesAsync(); 
} 

しかし、第三段階では、SaveChangesAsync()

で失敗します10

System.InvalidOperationException:データベースへの変更は正常にコミットされましたが、オブジェクトコンテキストの更新中にエラーが発生しました。 ObjectContextが矛盾した状態になっている可能性があります。内部例外メッセージ:「DbModels.PersonModel」タイプの複数のエンティティが同じ主キー値を持つため、変更の保存または受け入れに失敗しました。

テーブルをクリアして(別の主キーを使用して)別のエントリを追加してから最初のステップからエントリを追加すると、正常に動作し、両方のエントリが例外なく保存されます。

テーブルをクリアした後に新しいエントリを作成する直前にブレークポイントを追加し、テーブルが空である(id = 1のエントリがない)ため、Personsテーブルを外部ツールでチェックしました。

UPDATE: 拡張DbContexte +私のCreateメソッドの実装:

public DbSet<PersonModel> Persons { get; set; } 

    public T Create<T>(T entity) 
     where T : class 
    { 
     try 
     { 
      GetDbSetForType<T>().Add(entity); 
      return entity; 
     } 
     catch (Exception ex) 
     { 
      return default(T); 
     } 
    } 

    private DbSet<T> GetDbSetForType<T>() 
     where T : class 
    { 
     var type = typeof(T); 

     if (type == typeof(PersonModel)) return Persons as DbSet<T>; 
     //...my other types 
     throw new Exception("Type not found in db"); 
    }  
+0

context.Create(person2) - これは独自の方法ですか?私はEFがそれを持っていることを覚えていないので。もしそうなら - それを見せてもらえますか? – Toddams

+0

@Toddamsああ、申し訳ありませんが、私のCreateメソッドの本体を質問に追加しました –

+0

PersonModelsからすべてのエントリを削除した場合、これを代わりに使うことができます: 'await context.Database.ExecuteSqlCommandAsync(string.Format(" TRUNCATE TABLE 'PersonModels' "));'それはあなたのために働くだろうか? – LocEngineer

答えて

0

EFデータベースコンテキストは、それが破壊されたりアンロードされるまで、それは、インメモリデータベースから取得したオブジェクトのリストを維持します。

using (var ctx = new MyDbContext()) 
{ 
    var person1 = new Person { Id = 1 }; 
    ctx.Persons.Add(person1); 
    await ctx.SaveChangesAsync(); 

    await context.Database.ExecuteSqlCommandAsync(string.Format("DELETE FROM `PersonModels`")); 

    // This is the secret 
    ((IObjectContextAdapter)ctx).ObjectContext.Detach(person1); 

    ctx.Persons.Add(person1) 
    await ctx.SaveChangesAsync(); 

} 
+0

ありがとうございます、私は別のコンテキストを使用しています(Personsテーブルをクリアした後、コンテキストを破棄してエントリを追加するコンテキストの新しいインスタンスを作成します)。また、私の((IObjectContextAdapter)ctx).ObjectContextにPersonsが含まれていません(DbContext - > 'DbSet Persons'の私の実装にPersonsプロパティしかありませんが、DbSetはDetach()を持っていません) –

+0

あなたが記述した状況の下では間​​違いなく問題を再現できませんでした。私は 'Detach'コードサンプルも更新しました。 –

関連する問題