Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/262.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何放弃对EF Core中上下文的更改_C#_.net_Entity Framework_Entity Framework Core - Fatal编程技术网

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

C# 如何放弃对EF Core中上下文的更改,c#,.net,entity-framework,entity-framework-core,C#,.net,Entity Framework,Entity Framework Core,我有一个json格式的“扁平化”对象的巨大列表,以及一个有点复杂的关系数据库模式(大约有20个表对应于扁平化对象)。我正在尝试在新的关系数据库中自动插入这些扁平对象: foreach (var flattenedObject in flattenedObjects) { _repository.Insert(flattenedObject).Wait(); //some time logging, etc } Insert()方法为不同表中的许多相关对象调用addRangeAy

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

foreach (var flattenedObject in flattenedObjects)
{
    _repository.Insert(flattenedObject).Wait();
    //some time logging, etc
}
Insert()
方法为不同表中的许多相关对象调用
addRangeAync()
AddAsync()

由于展平对象是遗留对象,我想说大约0.001%的对象格式不正确,并且会违反DB约束—例如,尝试在其中一个表中插入重复的复合主键

我预计会出现这些罕见的错误,因此我的想法是-在事务中包装整个
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块中的某个地方发生错误(我尝试插入一个违反复合主键的对象),我的整个上下文对象就会损坏

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

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

_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);

在分离之前,您是否应该在.where(e=>e.Entity!=null&&e.state==EntityState.Added)中包含以下条件这对于我当前的插入导致问题的场景是正确的。但是,有些人在更新时可能会遇到类似的问题,因此,如果其他人遇到此类问题,我会将此答案保留为“复制+粘贴”。将上下文中存在的每个实体与context.Reload()相等,当下次使用上下文时。这将对数据库产生巨大的影响。因为这与创建上下文对象againcontext是一样的。重载()正是我在这个问题中寻找的。尽管如此,它似乎并没有成为标准EF核心包的选项。在EF核心3.1上,我找不到一个重新加载选项本身;但是,在分离ChangeTracker中的所有条目之后——使用上述代码——我可以调用context.SaveChanges()来有效地重置它(解析并丢弃所有分离的条目,将更改计数保留为零,并有效地保存零内容,因此不会对数据库产生影响)。然后继续使用上下文。