2011-08-29 125 views
3

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

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

在此先感谢

+0

需要考虑的事情:浏览器崩溃,会话超时,用户在离开办公桌,返回键等 –

回答

1

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

0

这是网络上难以做到的事情。我建议在User1访问数据时在数据库中使用TimeStamp。然后给User1一种手动解锁页面的方法,并且如果User1放弃页面(导航,关闭浏览器,丢失互联网连接等),则使用超时值利用TimeStamp自动解锁用户2的记录。 。

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

如果你是一个网络农场吗? –

+0

作为一个告诫,我应该提到,只有当你有一个Web服务器时,这才会起作用。如果你有多个服务器,您将需要存储的事实,页面被锁定在某处(大概是一个数据库),然后你会检查的记录被锁定的时间的时间戳。 – aquinas

+0

不要试图揉搓你错误,那只是为了别人,不知道他们会进入什么。 –

2

如果你试图锁定一条记录,你100%会得到陈旧的锁,这意味着你必须有一个过程来删除这些陈旧的锁。

如果您只是试图阻止并发修改,您可以使用时间戳或版本字段进行此操作。编辑记录时,将版本/时间戳放入隐藏字段。然后,在尝试应用更新时,首先要重新读取与该ID对应的数据,然后根据隐藏字段中的版本检查数据库返回的版本。如果它们匹配,那么继续前进并应用更改是安全的,如果不匹配,则可以应用一些逻辑来确定如何继续。

1

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

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

我不是说这是一个很好的解决方案,但它是一个想法。我所知道的是,因为你不能分辨浏览器是否关闭,你需要在盒子外面思考。

2

为了获得良好的用户体验,我在用户点击使用JavaScript编辑后在页面上设置了心跳。每5秒钟或更合理的我会ping服务器。因此,如果用户由于某种原因而断开连接,则可以通过关闭用于查看用户最后一次ping页面的线程来快速释放锁定。您必须将ping时间存储在某处,例如服务器缓存或会话,但我更喜欢像memcache这样的分布式缓存进行负载平衡(尽管在您的环境中它可能不重要)。

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

1

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

交互设计规则1“用户”不会做你期望的 - 有史以来。

锁定规则1 - 如果负责释放锁的actor可能会失败。即使您通过休克疗法来管理您的用户群,但他们的计算机可能会失败,数据库可能会失败,连接可能失败,网络可能失败,用户可能会在编辑过程中死亡。

规则2的锁定东西 - 当锁定东西的规则1有效时,你需要一个out-specific TIMEOUT或其他释放孤立锁定的方法。

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

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

  1. 用户点击编辑
  2. 请求锁项目要被编辑(时间为5分钟呢?)收购
    • 在成功GOTO 3
    • 如果失败通知用户锁未获得通过锁定令牌
      • 返回
    • 检查项目的版本,如果版本是相同的(不可能是老年人吧?)GOTO 5
    • 如果版本较新的GOTO 4
  3. 检索最新版本从服务器的项目
  4. 进入编辑模式
  5. 定期测试锁的年龄并通知用户在锁即将到期

具体来说,我们将与尹的想法取代第6项以不打扰用户发出通知,但要使用大约30秒的“微型锁定持续时间”,并通过从客户端延长锁定持续时间超过30秒来保持锁定状态。