gpt4 book ai didi

c# - 如何放弃对 EF Core 中上下文的更改

转载 作者:太空狗 更新时间:2023-10-29 20:07:00 26 4
gpt4 key购买 nike

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

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

Insert() 方法为不同表中的多个相关对象调用AddRangeAsync()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 block 中某处发生错误(我尝试插入一个违反复合主键的对象),我的整个上下文对象就会损坏。

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

我尝试为上面的 foreach 循环中的每个新对象重新创建我的 DbContext 和 repo - 但即便如此,如果我查询:

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

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

有没有什么(优雅的)方法告诉我的上下文重置所有未决的更改——这样我就可以在发生错误时将它放在 catch block 中?我希望在我失败的交易中发生的一切都保留在那里而不是泄漏。

最佳答案

下面的代码对我有用。但是,如果有人发布了更简洁的解决方案(我仍然希望 EF 有一些开箱即用的东西),我会接受它。

private void ResetContextState() => _context.ChangeTracker.Entries()
.Where(e => e.Entity != null).ToList()
.ForEach(e => e.State = EntityState.Detached);

关于c# - 如何放弃对 EF Core 中上下文的更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42885020/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com