我有一个记录列表,我正在尝试使用 Entity Framework Core 将其插入到 SQL 数据库中。
我正在尝试使用循环保存记录。我的 CRUD 服务只是将记录添加到
DbSet
并调用 SaveChangesAsync()
(是的,我知道我应该调用 SaveChanges
一次或使用 AddRange
,但目前它是这样分割的)。
foreach (var record in records)
{
var result = await _crud.CreateAsync(record);
if (result.HasError)
// log error
}
现在,第一条记录有效并且保存完好。
第二条记录会导致错误,正常,因为它被记录了。
但是,问题就在这里。此后的每条记录都会失败,即使它们是有效的。收到的错误消息(和数据)与记录 2 相同。就好像该记录没有从上下文中删除或清除。
出了什么问题?
根据这个“_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);
}
请注意,如果记录包含创建/添加的任何子实体,则也需要分离这些子实体。任何对现有实体的引用都不应被分离。