【问题标题】:RemoveRange throws InvalidOperationException in Entity Framework CoreRemoveRange 在 Entity Framework Core 中抛出 InvalidOperationException
【发布时间】:2016-10-18 19:38:56
【问题描述】:

我得到错误:

无法跟踪实体类型“瞳孔”的实例,因为另一个 已在跟踪具有相同密钥的此类实例。什么时候 添加新实体,对于大多数键类型,一个唯一的临时键值 如果没有设置键(即,如果键属性已分配)将被创建 其类型的默认值)。如果您明确设置密钥 新实体的值,确保它们不会与现有实体发生冲突 为其他新实体生成的实体或临时值。什么时候 附加现有实体,确保只有一个实体实例具有 给定的键值附加到上下文。

如果我会在此实例之前检索该实例,然后将其加载到上下文缓存中,我会理解此错误,但我没有!!!

    var pupilsToDelete = pupilIds.Select(id => new Pupil { Id = id });
    context.RemoveRange(pupilsToDelete.ToList());
    await context.SaveChangesAsync();

在运行期间,学生 ID 都是不同的 ID!

为什么会出现这个错误?

【问题讨论】:

  • 您是否 100% 确定没有加载任何 Pupils? pupilIds 来自哪里?你有一个新的上下文实例吗?
  • 未从数据库加载学生。我还尝试了 context.entry(new Pupil(id = id).state = state.Deleted 并像在 EF6 中那样做了 context.savechanges() 但确实也导致了异常......

标签: c# entity-framework-core


【解决方案1】:

要删除记录,需要从上下文中进行跟踪。因此,不要创建 Pupil 的新集合,只需从上下文中引用它们

 var pupilsToDelete = context.Pupils.Where(a => pupilIds.Contains(a.Id)).Select(b => b);
 context.Pupils.RemoveRange(pupilsToDelete);
 await context.SaveChangesAsync();

【讨论】:

  • 该代码毫无意义,甚至无法编译;-) 将 .Select() 替换为 .Where()。让我们从那里开始。
  • 为什么不编译你的表名Pupils 还是不编译?您要从中删除条目?
  • 是的,我知道了,现在好的,现在检查,这是一个错误
  • 好的,代码工作了,但是为什么呢? RemoveRange 是否只删除被跟踪的实例?
  • 在您的代码中,您正在创建一个新的 Rupils 集合,该集合实际上并非来自数据库实例。您需要获取要删除的记录的实例
【解决方案2】:

为了能够删除记录,您需要确保您的 ObjectContext 正在跟踪它们。 @Mostafiz 回答了删除项目的最佳方法,但您也可以将实体附加到上下文。

var pupilsToDelete = pupilIds.Select(id => new Pupil { Id = id });
foreach(var p in pupilsToDelete )
   context.Attach(p);
context.RemoveRange(pupilsToDelete.ToList());
await context.SaveChangesAsync();

这不是好办法․

【讨论】:

  • 顺便说一句。存在一个 context.AttachRange(pupilsToDelete)...当我运行您的代码时,我在 RemoveRange 处遇到异常...似乎我在这里遇到了一个错误...
  • 我从未尝试过,但听说它很慢。在实体框架文档中,您可以阅读 RemoveRange 函数描述以及他们建议如何使用它。附加也不能更好,因为无论如何它需要找到所有ID。
  • context.AttachRange(pupilsToDelete) 也有错误?
  • 是的,它确实会抛出异常!
猜你喜欢
  • 2018-03-20
  • 2018-09-19
  • 1970-01-01
  • 1970-01-01
  • 2018-08-18
  • 2020-09-25
  • 1970-01-01
  • 2020-06-07
  • 1970-01-01
相关资源
最近更新 更多