【问题标题】:Locking the page in asp.net for a user为用户锁定 asp.net 中的页面
【发布时间】:2011-11-05 17:08:22
【问题描述】:

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

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

提前致谢

【问题讨论】:

  • 需要考虑的事项:浏览器崩溃、会话超时、用户离开办公桌、返回按钮等

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


【解决方案1】:

出于您提到的所有原因,我认为这是一个非常糟糕的主意,但如果我不得不这样做,我会做的是使用 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 缓存在两分钟后自动“解锁”记录。因此,您可以免费获得所有这些。

【讨论】:

  • 如果你在网络农场怎么办?
  • 作为警告,我应该提一下,这只有在您拥有一台 Web 服务器时才有效。如果您有多个服务器,则需要将页面锁定在其他地方(可能是数据库)的事实存储起来,然后检查记录锁定时间的时间戳。
  • 不想惹毛你,那只是为了其他不知道他们可能会遇到什么的人。
  • 完全没有,我什至在看到您的消息之前就发布了警告。你指出来是完全正确的。这是在某些情况下有效的一种方法。
【解决方案2】:

如果您尝试锁定记录,您将 100% 获得过时的锁,这意味着您必须有一个过程来移除这些过时的锁。

如果您只是想防止并发修改,您可以使用时间戳或版本字段来执行此操作。编辑记录时,将版本/时间戳放入隐藏字段。然后,当尝试应用更新时,您要做的第一件事是重新读取与 ID 对应的数据,然后检查从数据库返回的版本与隐藏字段中的版本。如果它们匹配,则可以安全地继续应用更改,如果不匹配,则可以应用一些逻辑来确定如何继续。

【讨论】:

    【解决方案3】:

    为了获得良好的用户体验,我会在用户使用一些 javascript 单击“编辑”后在页面上设置心跳。每 5 秒或更合理的时间我会 ping 服务器。因此,如果用户出于某种原因断开连接,您可以通过关闭一个线程来快速释放锁定,该线程检查用户最后一次 ping 页面的时间。您必须将 ping 时间存储在某个地方,例如服务器缓存或会话,但我更喜欢 memcache 之类的分布式缓存来实现负载平衡(尽管它在您的环境中可能并不重要)。

    锁本身应该很容易实现,但我更喜欢分布式缓存解决方案,如 memcache 或数据库中的时间戳列。如果它没有通过心跳过期,我仍然会包含故障安全过期。

    【讨论】:

      【解决方案4】:

      我曾在一个类似的系统上工作过,在我们的例子中,我们在数据库中的记录上设置了一个位,以表明它正在被编辑。但是,与您的情况不同,我们能够设置我们系统的最终用户的期望,即他们必须单击“保存”或“取消”以将位翻转并允许其他用户编辑记录。老实说,我不完全确定如何处理用户放弃页面的情况,但我想到的是有一个运行存储过程的计划任务,如果记录被锁定一段时间,它将释放记录时间(这意味着您还需要一个日期时间字段来指示记录何时被锁定)。

      【讨论】:

        【解决方案5】:

        这是不可能的,因为无法确定用户的浏览器是否已关闭。您可以做一些愚蠢的事情,例如通过让浏览器每分钟轮询您的网站(例如 ping)来推断浏览器已关闭,但我不会走那条路。您也可以在会话中使用 slideExpiration,但对我来说,会话​​应该用于会话而不是“锁定”页面。

        也许在缓存中保留页面名称的缓存值,该缓存记录已锁定文件的用户的记录,有效期为 10 分钟。如果另一个用户请求该文件,您的代码首先检查页面名称是否在缓存中。如果同一个用户请求同一个文件(即回发或刷新),则更新缓存(即重置计时器),他们将有额外的 10 分钟。假设用户正在写一封冗长的信,但他们还没有回复或刷新页面,并且 10 分钟已到,您可以通过在 9 分钟后触发并提醒用户“您的时间与页面将在 1 分钟后结束,单击“确定”可将您的时间再延长 10 分钟”。

        我并不是说这是一个很好的解决方案,但这是一个想法。我所知道的是,由于您无法判断浏览器是否已关闭,因此您需要跳出框框思考。

        【讨论】:

          【解决方案6】:

          @Brian Driscoll 说他们在数据库记录上做了一些设置。然后他们告诉他们的用户他们必须点击保存或取消。真的吗?这有很多问题。

          交互设计“用户”的规则 1 永远不会按照您的期望行事。

          锁定规则 1 - 如果负责释放锁定的参与者失败,它就会失败。即使您通过休克疗法设法训练您的用户群,他们的计算机可能会出现故障,数据库可能会出现故障,连接可能会出现故障,网络可能会出现故障,用户可能会在编辑过程中死亡。

          锁定规则 2 - 当锁定规则 1 生效时,您需要输出 - 特别是 TIMEout 或其他释放孤立锁的方式。

          在 WikiPedia 上有很多关于锁定的文章,值得一读。文件锁定和线程相关的锁定(互斥锁、信号量等)与这个问题非常相似,了解这些工作的原理是一个很好的起点。用户真的只是另一个外部并行处理单元吗?

          @Michael Yoon 在我看来给出了一个非常有趣的答案。我们正在实施这种基于页面的锁定,这就是我们现在的系统正在做的事情,但我们会将其更改为更像 Yoon 的想法,即不断 ping 服务器以延长锁定。

          1. 用户点击编辑
          2. 请求锁定要编辑的项目(持续时间 5 分钟?)
            • 成功后转到 3
            • 失败时通知未获取用户锁
          3. 检查锁定令牌返回的项目版本
            • 如果版本相同(永远不会更旧,对吗?)转到 5
            • 如果版本较新 GOTO 4
          4. 从服务器检索项目的最新版本
          5. 进入编辑模式
          6. 定期测试锁的年龄,并在锁即将到期时通知用户

          具体来说,我们将用 Yoon 的想法替换第 6 项,以免通知打扰用户,而是使用大约 30 秒的“微锁定持续时间”,并通过将来自客户端的锁定持续时间延长超过 30 秒来保持锁定处于活动状态秒。

          【讨论】:

            【解决方案7】:

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-01-09
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多