小编典典

asp.net mvc; 一次仅适用于一个用户的编辑选项

sql

我有一个表,其中包含三个带有一些记录的字段。如果用户要编辑表中的记录,则不允许其他用户同时编辑该记录。我可以采取什么样的步骤来实现这一目标?


阅读 152

收藏
2021-04-28

共1个答案

小编典典

来自桌面应用程序背景的许多人会想知道如何在Web应用程序中完成此操作。

锁定记录标志

在桌面环境中,一种方法是在该行上具有一个布尔值列,以指示其正在被编辑以及由谁编辑。您当然可以使用Web应用程序执行此操作,但这是一种非常糟糕的方法,因为如果用户访问“编辑”页面,将记录置于锁定状态,然后离开该页面,它将永远处于锁定状态。您没有确定的方式来告诉用户仍然没有打开编辑页面。

时间敏感锁

航空公司预订方法是上述方法的一种变体,但是您还将拥有一个LockedUntilUtc,它是一个日期时间,指示记录被锁定的时间。假设Bob访问了一个页面进行记录,当您从GET操作提供服务时,您还设置了lock标志,并将LockedUntilUtc设置为以后的10分钟。5分钟后,莎拉(Sarah)访问该页面,但由于您选中了LockedUntilUtc而收到了“当前锁定”错误,并且该错误在将来出现。又过了6分钟(自锁定以来总共11分钟),并且有人访问了该页面,并且LockedUntil已经过去,因此您将锁定授予新用户。

这似乎是一个合理的折衷方案,但是到处都是问题,一定会让用户感到沮丧。首先,没有简单的方法将需要访问权限的用户排队编辑记录。Sarah可以尝试10次,然后经过10分钟,Jimmy访问了该页面,由于他是锁到期后的第一个人,因此他抓住了下一把锁,而Sarah没有机会。莎拉给您的服务台打电话,说她等待了10分钟才能使锁失效,现在已经15分钟了,她仍然无法进入页面。您的服务台可能会怀疑她真的等了整整10分钟,来回接而至。

您还必须为当前拥有锁的任何人实现客户端计时器/显示,以便他们知道在锁到期之前还剩下多少时间。

乐观并发

在大多数情况下,这是正确的方法。实际上,您根本不会以任何方式锁定记录。相反,许多用户可以访问编辑页面。当他们保存编辑时,表单将同时包含原始值和新编辑的值。服务器将表格中的原始值与数据库中的当前值进行比较,以查看是否存在临时编辑。

原来的* 值是从过去(当Bob最初访问的编辑页面)的一些点。该 电流
值是来自现在。在过去和现在之间,如果Sarah也访问了编辑页面,并成功保存了对数据库值的更改,则Bob的 原始 值将不同于数据库中的 当前
值。因此,当Bob尝试保存他的更改时,服务器将看到他的 原始 值与 当前 值不同
*DB中的值,并引发错误。
您将需要决定如何处理这种情况。通常,您让用户知道其他人自此以来已经编辑了该页面,然后刷新页面,他们会丢失其编辑内容。实体框架支持乐观并发。

Ajax化的乐观并发

您也可以让客户端偶尔用原始值对服务器执行ping操作,以便服务器可以检查您的页面是否陈旧(即其他用户进行了某些更改)并弹出一条消息。通过提前通知用户另一个用户已经编辑了页面,从而改善了用户的体验。因此,他们在进行编辑时不会走得太远,而无论如何它们都会丢失。他们还可以从浏览器中记录/复制/粘贴其编辑内容,从而可以刷新页面并参考更改内容。

SQL Server中有一个Timestamp列,可以与Entity
Framework一起使用,以降低检查更改所涉及的开销。这样您就无需在每个客户端中保留原始值的完整记录,并将它们回传回:http : //www.remondo.net/entity-
framework-concurrency-checking-with-timestamp/

细化编辑

我们大量使用的一种方法是合并每个字段,并立即提交对单个字段的编辑。这是使用称为x-
editable的jquery库完成的。用户编辑单个字段,确认编辑,然后将该值发送到服务器。如果要检查整个记录的更改,或者仅检查单个字段,可以将其与乐观并发结合使用。如果检测到更改,则您拒绝编辑并刷新页面。对于用户而言,这可能是更友好的体验,主要是因为在编辑单个字段时,用户会立即收到“另一个用户编辑过的页面”错误。这样可以防止他们浪费大量时间编辑大量字段,而只是发现他们的编辑被拒绝,而他们不得不再次
重做所有编辑 。相反,他们只编辑一个字段,得到错误,刷新页面, 他们只需要重复一次该字段编辑并从那里继续

http://vitalets.github.io/x-editable/demo-
bs3.html

2021-04-28