2010-04-16 41 views
0

我不确定这是否是正确的术语,但这是什么id喜欢做: 我有一个使用mssql数据库的应用程序。 此应用程序可以在3种模式下运行。 模式1)用户不改变,但只读取数据库 模式2)用户可以向数据库中的表格添加行(一次一个) 模式3)用户可以改变数据库中的多个表格(一个人在一次)SQL锁定在Silverlight应用程序

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

谢谢

回答

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,它允许你在客户端安全地创建键),或者你可以使它成为int/identity column,然后使用SCOPE_IDENTITY()从表中检索值。我更喜欢GUID,但都可以。

如果您需要防止用户编辑可能在其下面发生更改的值,那么您将进入乐观与悲观的锁定状态。这是一个相当复杂的话题,但你可以开始here

在附注中,我提到需求听起来很奇怪。你至少应该看看各种各样的SQL Transaction Isolation Levels,看看是否设置任何这些会给你你需要的。

+0

嗨,谢谢你的回答。你为什么说这很奇怪?你是怎么意思的? 我假设您在退出应用程序时清除锁定。如果由于某种原因锁不起作用(浏览器崩溃等)会发生什么? – immuner 2010-04-16 13:51:59

+0

有关锁没有被清除的好处 - 我忘了你在这里处理WCF/Silverlight。我编辑了我的答案以反映这一点。 关于“怪异”,我的意思是这样的:当我遇到像你所描述的要求时,我总是试图找出他们的实际商业原因。很多时候,作为“要求”传递给我的是实际上有人试图在“解决方案”的基本要求。一旦你得到了真正的需求,你可能会找到比原先提出的更好的解决方案。 – 2010-04-16 17:45:55

+0

欢呼声我会看看这个。然而你怎么看待q2? 我想我可能没有解释清楚为什么我需要这个(根据需求),所以我会尽力解释更好。 我的应用程序包含一个地图,它允许添加存储在数据库中的点。 模式1适用于任何人都可以使用它来查看地图上的点。这只读取数据库。 模式2允许一些用户(当从管理员启用时)也在地图上添加一个点。这到q2这是重要的解决。 模式3更像是一个迷你cms,它可以更改应用程序的更多数据,这可能会由sessionid解决。 – immuner 2010-04-16 20:24:08

0

如果您使用WCF RIA服务,您可以选择通过采取不同的方法来解决问题,而不是事先锁定:如果用户提交的变更与数据库中自从打开数据库以来不同以他们的形式提供数据,您将通知他们冲突并让他们选择接受或拒绝部分或全部变更。这是因为RIA服务使您能够在向服务器提交更改之前拥有更改集。

Pluralsight培训的Yacine Khammal有一个梦幻般的演示here(付费墙,但是我花的最好的29美元)。查看名为“演示:处理验证和并发错误”的视频。

1

为了避免用户确实没有必要(因为他当时不被允许进行更改),我们需要做一个悲观的锁定。

因此,您建议的乐观锁定方法是从使用视角工作流程完全不同的东西。我认为,OP的困境与我们的一样。

Silverlight和服务通信是异步的,必须将一个打开的事务放入Session或类似的;而且还需要某种集合,因为不能有无限连接打开数据库。

还有一种悲观锁定的方法,不是通过事务,而是使用一个表格,在其中写入“锁定语句”(某些信息用于避免表和行被锁定),以便应用程序可以用来通知另一个用户尝试选择已编辑的数据进行编辑。

与使用事务处理方法相同,删除锁的问题非常棘手。