正确处理DbUpdateConcurrencyException

时间:2017-07-27 13:08:43

标签: c# winforms entity-framework-6 visual-studio-2017 optimistic-concurrency

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

  

使用Windows Presentation Foundation(WPF)或Windows时   表单,使用每个表单的上下文实例。这可以让你使用   上下文提供的更改跟踪功能。

我已经读过DBContext的生命周期应该尽可能短,但显然是WinForms(我正在使用),这个规则不适用,推荐别的东西。

当前设置

此外,我的应用程序遵循MVC模式,在我的控制器中,我已初始化DBContext。现在,当窗体关闭时,控制器实例也被置于其中,这就是上下文死亡的地方。如果重要的话,我也在使用Database First方法。

现在总是打开一个上下文(每个表单)似乎它有自己的便利(你可以轻松跟踪上下文的变化),但是,例如,我发现自己(作为一个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         
}

现在这似乎正在工作......因为我的上下文是打开的,只要我的表单是活着的,当我在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
}

在这种情况下处理Optimistic Concurrency错误的正确方法是什么?

0 个答案:

没有答案