【问题标题】:EF Core Saving error for two objects depending on a second equal one两个对象的EF Core保存错误取决于第二个等于一个
【发布时间】:2021-01-21 09:29:03
【问题描述】:

我有一个很长很长的 POCO 类(“FichaCliente”),在这里我将对其进行简化,强调 ObservableCollection 的属性:

{
  public int FichaCliente1 { get; set; }
  ...
  public int FichaClienteN { get; set; }

  public ObservableCollection<Reclamado> Reclamados { get; set; }

  public int FichaClienteN+2 { get; set; }
  ...
  public int FichaClienteN+M { get; set; }

}

“Reclamado”类也是一个相对较长的 POCO,它具有另一个类作为元素,即 UF 类。因此,我们可以将“Reclamado”理解为:

{
  public int Reclamado1 { get; set; }
  ...
  public int ReclamadoN { get; set; }

  public UF Uf { get; set; }

  public int ReclamadoN+2 { get; set; }
  ...
  public int ReclamadoN+M { get; set; }

}

作为UF类一个简单的POCO如下:

{
    public int Id { get; set; }
    public string Apelido { get; set; }
    public string Descricao { get; set; }
    public string Municipio { get; set; }
}

对数据库的 SAVE 操作仅由“SaveFichaAsync”方法处理,简单如下:

public async void SaveFichaAsync(FichaCliente ficha)
    {
        using (var context = new DataContext(_dBService))
        {
            context.FichasClientes.Update(ficha);
            await context.SaveChangesAsync();

            return;
        }
    }

可以肯定的是,“FichaCliente”可以根据需要拥有许多“Reclamado”。没关系,它有效! 为了清楚起见,UF 实体相当于我在美国的状态,因此,给定地址属于一个州(城市,州......)。由于“Reclamados”是不同的实体,我可以拥有一个或多个属于同一个 UF 的“Reclamados”。

这就是失败的地方!

如果我为两个或多个不同的“Reclamados”拥有相同的 UF,则会显示一个错误,就好像它保存了两次相同的 UF,尽管它们实际上是不同的,每个都属于不同的“Reclamados”。它不会两次保存相同的 UF。它为每个“Reclamado”保存一个

错误示例如下:

“无法跟踪实体类型‘UF’的实例,因为键值为‘{Id: 26}’的另一个实例已被跟踪。附加现有实体时,请确保只有一个具有给定键值的实体实例已附上。”

我该如何处理?

【问题讨论】:

  • 您是使用同一个对象 (UF) 还是创建新对象?
  • 它们是不同的实例...每个实例代表不同的“Reclamado”,不一样!
  • 只是更关注代码:我有固定数量的 UF,每个代表一个状态。每当我参考时,我显然使用的是现有的,因为状态只是那些。但是每个实体 UF 都属于不同的实体 Reclamado,所以它们不可能是一样的……
  • 只需删除行context.FichasClientes.Update(ficha);
  • 所以不会'保存到数据库中? :O

标签: c# sql-server database entity-framework entity-framework-core


【解决方案1】:

虽然如果您将持久性模型与实际业务代码解耦可以避免这种情况,但要解决您必须在 SaveChangesAsync 之前遍历所有 UF 并针对每个 UF 执行以下操作的问题

context.Entry(uf).State = EntityState.Unchanged;

【讨论】:

  • 错误已更改,即只是它的 Id... 'Reclamado' 无法跟踪,因为已在跟踪另一个具有键值 '{Id: 0}' 的实例。附加现有实体时,请确保仅附加一个具有给定键值的实体实例。'...
  • 但是,如果我使用 context.Entry(uf).State = EntityState.Added,它确实有效!!!
【解决方案2】:

您的条目已被上下文跟踪。只需删除行 context.FichasClientes.Update(ficha);,您的代码就可以运行。

Update 方法仅在条目未被 Context 跟踪时才有用。 Read more about update

【讨论】: