在Silverlight应用程序上的SQL锁定

时间:2010-04-16 01:05:38

标签: sql-server silverlight

我不确定这是否是正确的术语,但这就是我喜欢做的事情: 我有一个使用mssql数据库的应用程序。 该应用程序可以在3种模式下运行。 模式1)用户不会改变,但只读取数据库 模式2)用户可以将行(一次一个)添加到数据库中的表上 模式3)用户可以更改数据库中的多个表(一次一个人)

问题1)如何确保当模式3中的用户“锁定”并且在模式2或模式3下操作的所有登录用户都无法更改数据库直到他完成时? 问题2)我如何确保在模式2中有多个用户时,在更新表时不会发生冲突?我的猜测是,在添加新行之前,您要对表的当前唯一键进行服务器查询并添加新条目。这会安全吗?

由于

3 个答案:

答案 0 :(得分:1)

为了避免用户做不必要的事情(由于当时不允许他进行更改),人们会做一个悲观的锁定。

所以你建议的乐观锁方法是从使用透视工作流程中完全不同的东西。我认为,OP的困境与我们的相同。

Silverlight和服务通信是异步的,人们必须将开放的事务放入Session或类似的事务中;并且还需要某种池化,因为无法为数据库打开无限连接。

还有另一种悲观锁的方法,不是通过事务,而是使用一个表,你写一个“locktoken”(一些信息没有锁定表和行),应用程序可以使用它来通知另一个尝试的用户选择要编辑的数据,以便进行编辑。

删除锁定的问题与使用事务处理方法时的问题相同。

答案 1 :(得分:0)

有多种方法可以解决#1问题。假设你的要求是正确的(我至少要仔细检查它们,因为它们听起来很奇怪),我可能要做的就是创建一个看起来像这样的ApplicationLock表:

CREATE TABLE ApplicationLock(SessionId UniqueIdentifier,CreateDate DateTime,LockType int,Active bit)

然后,在您想要执行需要锁定的操作之前,请检查是否存在阻止您执行所需操作的类型的活动锁定。 (如果有,请查看是否通过了一些已定义的超时时间。如果超过某个超时时间,您应该能够清除锁定。)如果没有可以阻止您的锁定,请插入自己的锁定(您可以使用Guid.NewGuid()在Silverlight客户端上创建SessionId,执行您需要执行的操作,然后清除锁定。如果所有这些都发生在一个Web服务方法调用中,您应该确保将其包装在事务中,以便在出现故障时自动回滚锁。

关键是确保你的锁被清除。如果只需要为一个WCF方法调用挂起一个锁,那么你应该能够很容易地在服务器端代码中处理它。但是,如果他们需要在方法调用中持续存在,我认为您需要一个多部分策略。如果您在WCF服务(如Net.TCP)中使用面向连接的绑定,则可以处理客户端断开连接的事件,这将允许您自动清除它们已打开的任何锁定。但是,我不会依赖于此,而且作为后备,我会有某种超时。

对于#2(当多人编辑表时防止冲突),它取决于在业务级别存在哪些类型的冲突。如果您只是担心插入具有相同主键的两行,那么可以轻松解决这个问题。假设您有一个代理密钥作为您的PK,您应该将该代理密钥设为UniqueIdentifier(例如,GUID,允许您在客户端安全地创建密钥),或者您可以将其设为{{3}然后使用SCOPE_IDENTITY()从表中检索值。我更喜欢GUID,但两者都可以。

如果您需要阻止用户编辑可能已在其下方更改的值,那么您将进入乐观与悲观锁定。这是一个相当复杂的主题,但您可以启动int/identity column

另一方面,我提到这些要求听起来很奇怪。您至少应该查看各种here,并查看是否设置其中任何一项都可以满足您的需求。

答案 2 :(得分:0)

如果您使用的是WCF RIA服务,您可以选择通过采用不同的方法解决问题,而不是预先锁定:如果用户提交的更改与数据库中的更改不同,因为他们打开了在他们的表格中,您可以告知他们冲突,并让他们选择接受或拒绝部分或全部的变更。这是因为RIA Services使您能够在向服务器提交更改之前进行更改集。

Pluralight培训的Yacine Khammal有一个很棒的演示版本here(付费墙,但是我用过的最好的29美元)。请参阅名为“Demo:处理验证和并发错误”的视频。