正确处理 DbUpdateConcurrencyException

Whi*_*ind 5 c# winforms optimistic-concurrency entity-framework-6 visual-studio-2017

这是来自关于 DBContext 生命周期的文档:

使用 Windows Presentation Foundation (WPF) 或 Windows 窗体时,请为每个窗体使用一个上下文实例。这使您可以使用上下文提供的更改跟踪功能。

我读过 a 的生命周期DBContext应该尽可能,但显然在WinForms(我正在使用的)的情况下,这条规则不适用,建议使用其他规则。

当前设置

我的应用程序也遵循MVC模式,在我的控制器中,我已经初始化了DBContext. 现在,当表单关闭时,除其他外,控制器实例也会被处理,这就是上下文消失的地方。如果重要的话,我也使用数据库优先方法。

现在,始终打开一个上下文(按表单)似乎有其自身的便利(您可以轻松跟踪上下文的更改),但是例如,我发现自己(作为EF初学者)有一些疑问......看看这个情况:

我有IList在创建表单时初始化的用户(用户实体)。我运行我的应用程序的两个(甚至更多)实例,因为它旨在在多用户环境中工作。现在,假设用户 A 和用户 B 都加载了相同的记录(用户管理屏幕,所以他们都是管理员)......现在事情是这样的:

用户A对某些记录B进行更改(更新)用户对同一记录进行更改(更新)并将其保存到数据库 用户A尝试保存DbUpdateConcurrencyException被抛出...

现在这很好,我知道一个术语乐观并发,并说用户AB正在更新同一行(或同一列),我会处理这样的异常(如果我遗漏了什么,请纠正我):

catch (DbUpdateConcurrencyException ex)
{
    ex.Entries.Single().Reload();
    //Here I reload UI with a new changes, and ask a user to try again         
}
Run Code Online (Sandbox Code Playgroud)

现在这似乎有效......因为只要我的表单还活着,我的上下文就会打开,当我对 ex.Entries.Single() 执行 Reload() 时,列表中的特定用户(请记住我已经提到了之前的用户列表) 用实际的数据库值刷新,因此当我重新加载视图时,用户获得当前状态。

实际问题

到目前为止一切顺利......但例如在这种情况下:

用户A删除该行

用户B尝试在同一行(已删除的行)上更新和保存更改

我遇到了多个问题,我不知道处理它的正确方法是什么。

我想,我应该更新用户列表,但不知道如何在不处理当前上下文的情况下执行此操作。所以这将是一个问题......如何从数据库重新加载用户列表,而不在此代码块中处理上下文:

catch (DbUpdateConcurrencyException ex)
{
    // Reload the user list with navigation properties fully initialized (note that user list is what would context.korisnik.ToList() would return)
    // Reload the UI
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下处理乐观并发错误的正确方法是什么?