【发布时间】: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 命令从现有表。)
-
太糟糕了。但是,根据stackoverflow.com/questions/10854906/…,您可以通过在事务中运行删除命令并提交该事务来解决此问题。
标签: c# database entity-framework sqlite