我遇到了锁定asp.net页面的问题。我们有一个用户个人资料页面,我们需要在该页面中为首先打开它的用户锁定该页面。详细信息如下,数据库中有许多用户配置文件记录,我们将记录号传递给查询字符串以打开特定页面。用户单击网格中的链接按钮并以只读模式打开记录。有一个编辑按钮,可以启用所有控件,并在用户单击它后将其提供给用户。任务是将记录锁定到首先单击编辑按钮的用户。
除此之外,还有许多场景,例如用户可以从页面导航,或者他可以在两者之间关闭页面。在这些情况下,记录应该可供其他用户使用。 请给我一些可能的方法或如何解决方案的例子。
提前致谢
答案 0 :(得分:2)
我认为这是你提到的所有原因的一个非常糟糕的主意,但如果我有这样做,我会做的是使用ASP.NET缓存。
所以,像这样:
Cache.Add(someUniqueKeyForAUserProfile, theUserThatLockedTheRecord, null,
DateTime.Now.AddSeconds(120), Cache.NoSlidingExpiration, CacheItemPriority.Normal,
UnlockRecord)
private static void UnlockRecord(string key, object value, CacheItemRemovedReason reason) {
//This particular record went longer than 2 minutes without
//the user doing anything, do any additional cleanup here you like
}
然后在页面中您可以执行以下操作:
if (Cache[someUniqueKeyForAUserProfile] != theUserThatLockedTheRecord){
//Tell the user they can't access the page
}
这里的好处是你可以在两分钟后使用内置的ASP.NET缓存自动“解锁”记录。所以你可以免费获得所有这些。
答案 1 :(得分:2)
如果您尝试锁定记录,则100%将获得陈旧锁定,这意味着您必须有一个过程来删除这些陈旧锁定。
如果您只是想阻止并发修改,可以使用时间戳或版本字段执行此操作。编辑记录时,将版本/时间戳放入隐藏字段。然后,在尝试应用更新时,首先要做的是重新读取与ID对应的数据,然后根据隐藏字段中的版本检查从数据库返回的版本。如果它们匹配,那么继续并应用更改是安全的,如果不匹配则可以应用一些逻辑来确定如何继续。
答案 2 :(得分:2)
为了获得良好的用户体验,我会在用户使用某些javascript点击“编辑”后在页面上设置心跳。每隔5秒或者更合理的事情我会ping服务器。因此,如果用户因任何原因断开连接,您可以通过旋转检查上次用户ping页面的线程来快速释放锁定。你必须在某个地方存储ping时间,比如服务器缓存或会话,但是我更喜欢像memcache这样的分布式缓存来实现负载平衡(虽然它在你的环境中可能并不重要)。
锁本身应该相当简单,但我喜欢分布式缓存解决方案,如memcache或数据库中的时间戳列。如果它没有通过心跳到期,我仍然会包含故障安全过期。
答案 3 :(得分:1)
我曾经在一个类似的系统上工作过,在我们的例子中,我们在数据库中设置了一些记录,表明它正在被编辑。但是,与您的情况不同,我们能够为系统的最终用户设置期望,他们必须单击“保存”或“取消”以翻转该位并允许其他用户编辑记录。我真的不完全确定如何处理用户放弃页面的情况,尽管我想到的是有一个运行sproc的计划任务,如果它已被锁定一段时间,它将释放记录时间(这意味着您还需要一个日期时间字段来指示记录何时被锁定)。
答案 4 :(得分:1)
这是不可能的,因为无法确定用户的浏览器是否已关闭。你可以做一些愚蠢的事情,例如推断浏览器已关闭,例如让浏览器每分钟浏览一次你的网站(比如ping),但我不会那样做。您也可以在会话中使用slideExpiration,但对我而言,会话应该用于会话而不是“锁定”页面。
可能在缓存中保留页面名称的缓存值,该值保留已锁定文件的用户的记录,其中包含10分钟的到期时间。如果另一个用户请求该文件,您的代码首先检查页面名称是否在缓存中。如果同一用户请求相同的文件(即进行回发或刷新),则更新高速缓存(即重置计时器),并且他们将有额外的10分钟。假设用户正在写一封长信,他们没有回发或刷新页面,10分钟就到了,您可以通过让客户端计时器在9分钟后触发并通知用户“您的时间”来解决这个问题。该页面将在1分钟后结束,单击“确定”将您的时间延长10分钟“。
我不是说这是一个很好的解决方案,但这是一个想法。我所知道的是,因为您无法判断浏览器是否已关闭,您需要在框外思考。
答案 5 :(得分:1)
@Brian Driscoll说他们在数据库记录上设置了一点。然后他们告诉用户他们必须点击保存或取消。真?这有很多问题。
交互设计规则1"用户"不会做你期望的 - 永远。
锁定内容的规则1 - 如果负责释放锁定的actor可能会失败。即使您通过休克疗法管理您的用户群,他们的计算机可能会失败,数据库可能会失败,连接可能会失败,网络可能会失败,用户可能会在编辑过程中死亡。
锁定内容的规则2 - 当锁定内容的规则1生效时,您需要一个out - 特别是TIMEout或其他一些释放孤立锁的方法。
有很多关于锁定WikiPedia的文章值得一读。文件锁定和线程相关的锁定(互斥,信号量等)与这个问题非常相似,并且理解这些工作是一个很好的起点。用户真的只是另一个外部并行处理单元吗?
@Michael Yoon在我看来给出了一个非常有趣的答案。我们正在实现这种类型的基于页面的锁定,这就是我们系统现在所做的事情,但我们将其更改为更像是Yoon的想法,不断ping通服务器以扩展锁定。具体来说,我们会用Yoon的想法取代第6项,以免通知用户,但使用"微锁持续时间"可能需要30秒,并且通过从客户端延长锁定持续时间超过30秒来保持锁定活动。
答案 6 :(得分:0)
在网络上做这件事很难。当User1访问数据时,我建议在数据库中使用TimeStamp。然后给User1手动解锁页面,并使用TimeStamp超时值自动解锁User2的记录,如果User1放弃页面(导航离开,关闭浏览器,丢失互联网连接......等)