【问题标题】:Removing range using EF Core使用 EF Core 删除范围
【发布时间】:2017-08-25 15:26:37
【问题描述】:

在我的单元测试中,使用 InMemoryDatabase 使用 RemoveRange 批量删除数据时出现错误。

代码如下:

public void DeletePatient(Paciente patient)
{
    var schedules = dbContext.Schedules.AsNoTracking().Where(x => x.PatientId == patient.Id).ToList();
    dbContext.Schedules.RemoveRange(schedules);

    dbContext.Patients.Remove(patient);
}

这会引发此错误:

InvalidOperationException:无法跟踪实体类型“Schedule”的实例,因为已经在跟踪具有相同键的该类型的另一个实例。添加新实体时,对于大多数键类型,如果未设置键(即,如果键属性为其类型分配了默认值),则会创建一个唯一的临时键值。如果您为新实体显式设置键值,请确保它们不会与现有实体或为其他新实体生成的临时值发生冲突。附加现有实体时,请确保只有一个具有给定键值的实体实例附加到上下文。

但是,如果我执行一次 foreach 并重新加载每个实体,它就会起作用:

foreach(var item in schedules)
{
    var h = dbContext.Schedules.Find(item.Id);
    dbContext.Remove(h);
}

同样的foreach,直接使用item会报同样的错误:

foreach(var item in schedules)
{
    dbContext.Remove(item);
}

【问题讨论】:

  • @SamiKuhmonen,我正在使用 InMemoryDatabase,它没有事务。
  • 如果您打算进行更改,为什么要使用AsNoTracking()
  • @PanagiotisKanavos,我是 EF 的新手。我认为只有更新才需要跟踪。
  • 这正是你正在做的。更新数据库。 AsNoTracking() 仅在您不想想要进行任何修改时使用,只需加载一些实体

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


【解决方案1】:

尝试删除 AsNoTracking 子句。我尚未对其进行测试,但我的猜测是这会导致 EF 从数据库中重新读取实体,而不是在上下文中找到已经存在的实体。如果没有该子句,它应该在上下文中找到要删除的实际实体。

【讨论】:

  • 无需测试。跟踪用于启用更改并跟踪用户执行的修改。如果没有跟踪,当调用 SaveChanges 时,EF 只会看到它必须保存到数据库中的实体列表
猜你喜欢
  • 2018-07-19
  • 1970-01-01
  • 2021-05-08
  • 1970-01-01
  • 2021-11-30
  • 2020-07-09
  • 2019-06-20
  • 1970-01-01
相关资源
最近更新 更多