在asp.net中为用户锁定页面

时间:2011-08-29 01:11:06

标签: c# asp.net session checkout record-locking

我遇到了锁定asp.net页面的问题。我们有一个用户个人资料页面,我们需要在该页面中为首先打开它的用户锁定该页面。详细信息如下,数据库中有许多用户配置文件记录,我们将记录号传递给查询字符串以打开特定页面。用户单击网格中的链接按钮并以只读模式打开记录。有一个编辑按钮,可以启用所有控件,并在用户单击它后将其提供给用户。任务是将记录锁定到首先单击编辑按钮的用户。

除此之外,还有许多场景,例如用户可以从页面导航,或者他可以在两者之间关闭页面。在这些情况下,记录应该可供其他用户使用。 请给我一些可能的方法或如何解决方案的例子。

提前致谢

7 个答案:

答案 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通服务器以扩展锁定。

  1. 用户点击修改
  2. 请求锁定要编辑的项目(持续时间5分钟?)
    • 成功GOTO 3
    • 失败时通知用户锁未获取
  3. 检查锁定令牌返回的项目版本
    • 如果版本相同(永远不会更老,对吗?)GOTO 5
    • 如果版本较新GOTO 4
  4. 从服务器
  5. 检索项目的最新版本
  6. 进入编辑模式
  7. 定期测试锁定的时间并在锁定即将到期时通知用户
  8. 具体来说,我们会用Yoon的想法取代第6项,以免通知用户,但使用"微锁持续时间"可能需要30秒,并且通过从客户端延长锁定持续时间超过30秒来保持锁定活动。

答案 6 :(得分:0)

在网络上做这件事很难。当User1访问数据时,我建议在数据库中使用TimeStamp。然后给User1手动解锁页面,并使用TimeStamp超时值自动解锁User2的记录,如果User1放弃页面(导航离开,关闭浏览器,丢失互联网连接......等)