如何在 EF Core 中放弃对上下文的更改

2024-02-25

我有一个巨大的 json 格式的“扁平化”对象列表,以及一个有点复杂的关系数据库模式(大约 20 个表对应于一个扁平化对象)。我正在尝试在新的关系数据库中自动插入这些扁平对象:

foreach (var flattenedObject in flattenedObjects)
{
    _repository.Insert(flattenedObject).Wait();
    //some time logging, etc
}

The Insert()方法调用AddRangeAsync() and AddAsync()对于不同表中的多个相关对象。

由于展平的对象是遗留的,我想说其中大约 0.001% 的对象格式错误,并且会违反数据库约束 - 例如尝试在其中一个表中插入重复的复合主键。

我预计这些罕见的错误,因此我的想法是 - 包裹整个Insert()事务中的操作 - 如果操作的任何部分无效,则不要插入任何内容并记录错误,这样我可以在重试之前手动修改展平对象。因此我的代码看起来有点类似于:

public async Task Insert(FlattenedObject fo)
{
    using (var transaction = _context.Database.BeginTransaction())
    {
        try
        {
            //magical code that calls AddAsync for multiple tables
        }
        catch (Exception ex)
        {
            transaction.Rollback()
            //logging
        }
    }
}

但是,如果我的 try 块中的某个位置发生错误(我尝试插入违反复合主键的对象),我的整个上下文对象就会损坏。

导致异常的对象仍然保留在我的 DbContext 和任何后续调用中AddAsync()在不同的事务中触发新的异常。

我尝试为每个新对象重新创建 DbContext 和存储库foreach上面循环 - 但即使如此,如果我查询:

_context.ChangeTracker.Entries().Where(e => e.State != EntityState.Unchanged);

我看到我的旧对象仍在 dbContext 的新实例中。

有没有什么(优雅的)方法来告诉我的上下文重置所有挂起的更改 - 以便我可以在发生错误时将其放入 catch 块中?我希望失败的交易中发生的所有事情都保留在那里而不是泄漏。


下面的代码对我有用。但是,如果有人发布更清晰的解决方案(我仍然希望 EF 能提供开箱即用的解决方案),我会接受它。

private void ResetContextState() => _context.ChangeTracker.Entries()
    .Where(e => e.Entity != null).ToList()
    .ForEach(e => e.State = EntityState.Detached);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 EF Core 中放弃对上下文的更改 的相关文章

随机推荐