我有一个表有三个记录的字段。如果用户要从表中编辑记录,则不允许其他用户同时编辑该记录。我可以采取什么样的步骤来实现这一目标?
答案 0 :(得分:8)
来自桌面应用程序背景的很多人都会想知道如何在Web应用程序中完成此操作。
桌面世界中的一种方法是在行上有一个布尔列,表示正在编辑它,以及由谁编辑。您当然可以使用Web应用程序执行此操作,但这是一种非常糟糕的方法,因为如果用户访问“编辑”页面,将记录置于锁定状态,然后离开页面,它将永远处于锁定状态。您没有明确的方法来判断用户是否仍然打开了编辑页面。
航空公司预订方法是上述的变体,但您也会有一个LockedUntilUtc,它是一个日期时间,表示记录被锁定的时间。让我们说Bob访问一个记录页面,当从GET操作服务apge时,你也设置了锁定标志,并将LockedUntilUtc设置为10分钟。 5分钟后,莎拉访问了该页面,但获得了#34;目前被锁定了#34;错误,因为您检查了LockedUntilUtc,它目前在将来。再过6分钟(锁定后总共11分钟),有人访问该页面,LockedUntil现在已经过去了,所以你将锁定给新用户。
这似乎是一个合理的妥协,但它充满了肯定会让用户感到沮丧的问题。首先,没有简单的方法来排队需要访问权限的用户来编辑记录。 Sarah可以尝试10次,然后就在它经过10分钟时,Jimmy访问了该页面,因为他是锁定过期后的第一个人,他抓住了下一个锁定而Sarah没有机会。 Sarah打电话给你的服务台,说她等了10分钟才能锁定到期,现在已经15分钟,她仍然无法进入该页面。你的帮助台可能会怀疑她真的等了整整10分钟,然后来回。
您还必须为当前拥有锁定的人实施客户端计时器/显示器,以便他们知道在它们到期之前还剩多少时间。
在大多数情况下,这是正确的方法。你根本不以任何方式锁定记录。相反,许多用户可以访问编辑页面。当他们保存编辑时,表单包括原始值和新编辑的值。服务器将比较表单中的原始值和数据库中的当前值,以查看是否存在临时编辑。
原始值来自过去的某个时刻(当Bob最初访问编辑页面时)。 当前值现在来自。在过去和现在之间,如果Sarah也访问了编辑页面并成功保存了对数据库值的更改,那么Bob的原始值将与当前数据库中的值。因此,当Bob尝试保存更改时,服务器将看到他的原始值与数据库中的当前值不同,并抛出错误。您需要决定如何处理这种情况。通常,您让用户知道其他人已经编辑过页面,并刷新页面,然后他们就会丢失编辑内容。实体框架支持乐观并发。
您还可以让客户端偶尔使用原始值ping服务器,以便服务器可以检查您的页面是否过时(即其他用户更改了某些内容)并弹出消息。这通过向用户提前通知另一用户已编辑该页面来改善用户的体验。因此,他们不会在进行编辑方面走得太远,无论如何他们都会失去编辑。他们还可以在浏览器中记录/复制/粘贴他们的编辑内容,以便刷新页面并参考他们所做的更改。
SQL Server中有一个Timestamp列,它可以与Entity Framework协同工作,以降低检查更改所涉及的开销。这样您就不需要在每个客户端保留原始值的整个记录并将其传回去:http://www.remondo.net/entity-framework-concurrency-checking-with-timestamp/
我们使用的一种方法是ajax' ify每个字段并立即对单个字段进行编辑。这是使用名为x-editable的jquery库完成的。用户编辑单个字段,确认编辑,并将该值发送到服务器。如果要检查整个记录的更改,或者只检查单个字段,可以将其与乐观并发相结合。如果检测到更改,则拒绝编辑并刷新页面。这对于用户来说可以是更友好的体验,主要是因为用户获得了另一个用户编辑的页面"编辑单个字段时立即出错。这可以防止他们浪费大量时间来编辑大量字段,但却发现他们的编辑遭到拒绝,他们必须再次重做所有编辑。相反,他们编辑单个字段,获取错误,页面刷新,他们只需重复一次字段编辑并从那里继续。