使用循环在实体框架中保存记录,失败后不会移至下一条记录

问题描述 投票:0回答:1

我有一个记录列表,我正在尝试使用 Entity Framework Core 将其插入到 SQL 数据库中。

  • 记录1有效
  • 记录 2 无效(假设这是重复密钥违规,但也可能是错误数据)
  • 记录3有效
  • 记录 x 有效

我正在尝试使用循环保存记录。我的 CRUD 服务只是将记录添加到

DbSet
并调用
SaveChangesAsync()
(是的,我知道我应该调用
SaveChanges
一次或使用
AddRange
,但目前它是这样分割的)。

foreach (var record in records)
{
    var result = await _crud.CreateAsync(record);

    if (result.HasError)
        // log error
}

现在,第一条记录有效并且保存完好。

第二条记录会导致错误,正常,因为它被记录了。

但是,问题就在这里。此后的每条记录都会失败,即使它们是有效的。收到的错误消息(和数据)与记录 2 相同。就好像该记录没有从上下文中删除或清除。

出了什么问题?

entity-framework-core savechanges
1个回答
0
投票

根据这个“_crud”引用是什么,您面临的问题称为中毒的 DbContext。您已告诉 EF 添加(或更新)无效的实体。该实体将保留在更改跟踪器中,直到您告诉 DbContext 忽略它。 (拆下来)

因此,如果您的 _crud.CreateAsync(record) 看起来像这样:

try
{  
    _context.Records.Add(record);
    await _context.SaveChangesAsync();
    return new SuccessResult(record);
}
catch (Exception ex)
{
    return new FailureResult(ex);
}

如果您想继续使用该 DbContext 实例,则需要从 DbContext 中删除任何无效的实体或中毒的实体。否则,需要缩短您的工作单元(DbContext 的生命周期)来处理每一行,以便为每个插入使用新的 DbContext 实例。这通常意味着传入 DbContextFactory 引用而不是 DbContext 实例。

因此在上面的示例中尝试对 DbContext 进行解毒:

catch (Exception ex)
{
    context.Entry(record).State = EntityState.Detached;
    return new FailureResult(ex);
}

请注意,如果记录包含创建/添加的任何子实体,则也需要分离这些子实体。任何对现有实体的引用都不应被分离。

© www.soinside.com 2019 - 2024. All rights reserved.