实体框架 6 和 SQLite - 无法创建条目 PK 之前删除的条目
Posted
技术标签:
【中文标题】实体框架 6 和 SQLite - 无法创建条目 PK 之前删除的条目【英文标题】:Entity Framework 6 and SQLite - cannot create entry with PK of entry deleted before 【发布时间】:2016-01-17 14:17:38 【问题描述】:我正在使用 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) 读完一些书后,我清除了整个 Persons 表:
using (var context = new MyDbContext())
await context.Database.ExecuteSqlCommandAsync(string.Format("DELETE FROM `PersonModels`"));
await context.SaveChangesAsync();
3) 我尝试添加与第一步中的条目具有相同主键的条目:person2 (with Id = 1)
using (var context = new MyDbContext())
context.Create(person2);
await context.SaveChangesAsync();
但在第 3 步中,SaveChangesAsync()
失败并显示
System.InvalidOperationException:对数据库的更改已成功提交,但在更新对象上下文时出错。 ObjectContext 可能处于不一致的状态。内部异常消息:保存或接受更改失败,因为多个“DbModels.PersonModel”类型的实体具有相同的主键值。
当我在清除表后添加一些其他条目(使用不同的主键)然后从第一步添加条目时,它工作正常并且两个条目都被保存,没有例外。
我直接在创建新条目之前添加了一个断点(在清除表之后)并通过外部工具检查了 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");
【问题讨论】:
context.Create(person2) - 这是你自己的方法吗?因为我不记得EF有它。如果是这样 - 你能展示一下吗? @Toddams 哦,对不起,我在问题中添加了我的 Create 方法的正文 如果你从 PersonModels 中删除所有条目,你可以改用这个:await context.Database.ExecuteSqlCommandAsync(string.Format("TRUNCATE TABLE 'PersonModels'"));
这对你有用吗?
@LocEngineer SQLite 不支持 TRUNCATE 命令(来自官方文档:不幸的是,我们在 SQLite 中没有 TRUNCATE TABLE 命令,但您可以使用 SQLite DELETE 命令从现有表。)
太糟糕了。但是,根据***.com/questions/10854906/…,您可以通过在事务中运行删除命令并提交该事务来解决此问题。
【参考方案1】:
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();
【讨论】:
谢谢,但我使用的是单独的上下文(在清除 Persons 表后,我处理上下文并创建一个新的上下文实例以添加条目)。另外,我的 ((IObjectContextAdapter)ctx).ObjectContext 不包含“Persons”(我的 DbContext 实现中只有 Persons 属性 ->DbSet<PersonModel> Persons
,但 DbSet 没有 Detach()。)
在您描述的情况下,我绝对无法重现该问题。我还更新了Detach
代码示例。以上是关于实体框架 6 和 SQLite - 无法创建条目 PK 之前删除的条目的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Visual Studio 2013 中为 sqlite 配置实体框架 6