实体框架6和SQLite - 在

时间:2015-10-19 09:27:03

标签: c# database entity-framework sqlite

我正在使用Entity Framework 6和SQLite数据库(System.Data.SQLite.EF6),但删除后我无法立即创建具有相同主键的条目。例如:

我的实体模型:

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

  public int Name { get; set; }
}

步骤进行:

1)我将此实体person1的实例(Id = 1)插入到我的人员表中。

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

2)发布一些书籍我用以下内容清除整个人物表:

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

3)我尝试添加与第一步中的条目相同的主键:person2(Id = 1)

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

但是在第3步中,SaveChangesAsync()失败并带有

  

System.InvalidOperationException:已成功提交对数据库的更改,但更新对象上下文时发生错误。 ObjectContext可能处于不一致状态。内部异常消息:保存或接受更改失败,因为多个“DbModels.PersonModel”类型的实体具有相同的主键值。

当我在清除表(使用不同的主键)之后添加一些其他条目然后从第1步添加条目时,它可以正常工作,并且两个条目都保存,没有例外。

我在创建新条目之前直接添加了断点(在清除表之后)并通过外部工具检查了Persons表,并且表是空的(因此没有id = 1的条目)。

更新: 扩展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");
    }    

1 个答案:

答案 0 :(得分: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();

}