【问题标题】:DbUpdateConcurrencyException: Entities may have been modified or deleted since entities were loadedDbUpdateConcurrencyException:自加载实体以来,实体可能已被修改或删除
【发布时间】:2018-01-09 14:00:44
【问题描述】:

我正在使用 EF6。

在我清除一个表并且我想向该表添加一个新条目后,我收到以下错误:

存储更新、插入或删除语句影响了意外数量的行 (0)。自加载实体后,实体可能已被修改或删除

删除数据库表的代码:

 public void ResetStatistics() {
        _lisDatabase.Database.ExecuteSqlCommand("TRUNCATE TABLE Sortedtubes");
        _lisDatabase.sortedtubes.Local.Clear();
 }

之后我想使用以下代码向该表添加一个新条目:

 Sortedtubes tube = new Sortedtubes();
 tube.Time = time;
 tube.Milliseconds = time.Millisecond.ToString();
 tube.Barcode = barcode;
 tube.Tubetype = tubeType;
 tube.Target = target;
 tube.Materialcode = materialCode;

 try {
        _lisDatabase.sortedtubes.Add(tube);
        _lisDatabase.SaveChanges(); // Error appears here
 } catch (DbUpdateConcurrencyException ex) {
        // maybe do something here?
 }

我尝试了 EF 文档中的建议,但没有成功: https://msdn.microsoft.com/en-us/data/jj592904

编辑

问题似乎是Clear() 方法(_lisDatabase.sortedtubes.Local.Clear();)。在我执行这个方法之后,错误出现在下一个SaveChanges()之后。

所以也许还有其他方法来处理这个问题?我的应用程序中有一个 GridView,它绑定到 sortedtubes 实体,我清除它,以便在截断表格时也清除 GridView。

【问题讨论】:

  • 我不确定我是否理解:你删除了你的表,然后你尝试在你删除的表中添加值?
  • ok delete 是我用 sql 命令“truncate table”清除表的错误词
  • _lisDatabase.sortedtubes.Local.Clear() 标记要删除的对象。它不只是清除本地集合。你最好使用一个新的_lisDatabase 实例。
  • 当您使用“ExecuteSqlCommand”时,您的 _lisDatabase 实例已更改。当您尝试保存更改时,看起来“其他人”更改了记录并且您的实例已过时。亚伦的回答应该没问题。

标签: c# entity-framework entity-framework-6


【解决方案1】:

在我看来,您的问题在于尝试截断表格并手动清除本地版本的 DbSet。您应该只更改您的 EF 实体并保存它们,然后这些更改会反映在数据库中。

这应该可行:

_lisDatabase.SortedTubes.RemoveRange(_lisDatabase.SortedTubes);
_lisDatabase.SortedTubes.Add(new SortedTube());
_lisDatabase.SaveChanges();

或者,试试这个:

https://stackoverflow.com/a/10450893/5392513

【讨论】:

  • 当我尝试 SaveChanges() 时,我得到了与标题相同的错误。对于您使用 RemoveRange 的解决方案和您链接的解决方案 :(
  • @cybertronic 不太可能。我唯一能建议的另一件事是在你的truncate 之后做一个context.SortedTubes.Load();
  • If i Load() after truncate 这似乎可行,但我使用 sortettubes 实体作为 Datagrid 的源,我也想清除它,所以我执行_lisDatabase.sortedtubes.Local.Clear(); 也是,但之后我再次收到错误。
  • 不要使用Clear()Load() 将清除您的 DbSet。您需要重新绑定网格。
  • 好的,我明白了,但是如何重新绑定一个对象?
【解决方案2】:

我怀疑您通过在Truncate 表之前跟踪而从具有相同上下文的数据库中检索条目,并且当您应用SaveChanges 时,EF 正试图删除Truncate 已删除的记录。因此,执行它的常用方法是从上下文创建一个新实例并应用操作。使用相同的上下文创建长数据库进程并不是一个好主意。因此,在您的情况下,如果您想要 truncate 表并使用相同的上下文稍后添加新条目,您应该在 truncate 操作之后分离所有跟踪的条目。

public void ResetStatistics()
{
    _lisDatabase.Database.ExecuteSqlCommand("TRUNCATE TABLE Sortedtubes");
    _lisDatabase.sortedtubes.Local.Clear();
    foreach (var entry in _lisDatabase.ChangeTracker.Entries<Sortedtubes>())
    {
        _lisDatabase.Entry(entry).State = EntityState.Detached;
    }
}

另外,如果可以在Truncate 表之前的查询中使用.AsNoTracking,则无需手动分离条目。

【讨论】:

  • 如果我尝试这个,我得到错误:“实体类型 DbEntityEntry`1 不是当前上下文模型的一部分。”在“_lisDatabase.Entry(entry).State = EntityState.Detached;”行中
  • 实体类型是什么?是 SortedTube 吗?
  • 是的,它是 Sortedtubes
  • "Entries" 这个 sn-p 应该是你的实体类型。
  • public virtual DbSet&lt;Sortedtubes&gt; sortedtubes { get; set; } 这是我在 LISDatabase 类中对 sortedtubes 的定义。
【解决方案3】:

所以.. 最后我想我找到了解决方案。

我的重置方法现在看起来像这样:

public void ResetStatistics() {
     _lisDatabase.sortedtubes.RemoveRange(_lisDatabase.sortedtubes);
     _lisDatabase.SaveChanges();
}

我的添加保持不变:

_lisDatabase.sortedtubes.Add(tube);
_lisDatabase.SaveChanges();

但“大”变化发生在我的 Sortedtubes 实体中。我将 Time 的类型从 DateTime 更改为普通的 String

来自:

[Key]
[Column(Order = 1)]
public DateTime? Time { get; set; }

到:

[StringLength(45)]
public string Time { get; set; }

问题似乎是 Sortedtubes 实体的 Time 属性的类型。但我不知道为什么。 如果有人想向我解释这个案例?

感谢大家的帮助。

【讨论】:

    猜你喜欢
    • 2013-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-20
    • 1970-01-01
    相关资源
    最近更新 更多