【问题标题】:Locking in EntityFramework - calling empty stored procedure releases lock acquired using sp_getapplockEntityFramework 中的锁定 - 调用空存储过程释放使用 sp_getapplock 获取的锁定
【发布时间】:2015-01-26 10:24:31
【问题描述】:

我在 SQL Server 数据库中有一个患者表。客户端连接到数据库并签出其中一名患者,然后对其进行一些操作并保存。

因为多个客户端可能同时访问患者。我想实现悲观锁定机制,这样如果一个客户端可以一次获得一个特定患者的锁定。

此外,如果其中一个客户端锁定了特定患者并且崩溃或关闭客户端应用程序,则应该释放锁定。如果发生崩溃,当我们检测到客户端与数据库的连接已关闭时,应该释放锁。

我发现我可以使用sp_getapplocksp_releaseapplock 来实现这一点,并在调用sp_getapplock 时指定@LockOwner = 'Session',这样可以确保在与客户端的数据库会话关闭时释放锁。

从代码中,我调用数据库中的存储过程来获取锁。这会正确获取锁,如果我关闭客户端应用程序或客户端应用程序崩溃,锁就会被释放。这是我想要的行为。

当我调用另一个应该释放锁的存储过程时,就会出现问题。一旦进入存储过程,锁就会被释放,甚至在我们执行sp_releaseapplock @patientId, @LockOwner = 'Session'之前,实际上应该释放锁的行。

我尝试创建一个空的存储过程(只是注释掉了

DECLARE @result int
EXEC @result = sp_releaseapplock @patientId, @LockOwner = 'Session'

这个存储过程仍然释放我使用sp_getapplock 获得的锁。我似乎无法理解为什么会这样。只有当我明确调用 `sp_releaseapplock @patientId, @LockOwner = 'Session'``时才应该释放它

CREATE PROCEDURE [dbo].[uspReleaseAppLock]
    @patientId nvarchar(max),               -- Patient ID
    @ReturnValue int Output
AS
BEGIN
   DECLARE @result int
   EXEC @result = sp_releaseapplock @patientId, @LockOwner = 'Session'
   SET @ReturnValue = @@SPID
END

谁能告诉我为什么会这样。我在这里想念什么?我检查了两个存储过程(用于获取和释放锁)的会话 ID 是否相同,因此实体框架似乎没有为每次调用存储过程创建一个新会话。还有一些我无法理解的事情正在发生。有什么想法吗?

【问题讨论】:

  • 为什么你认为你需要悲观锁? SQL Server 针对 乐观 锁定进行了优化,我从不觉得需要做其他事情 - 即使在有数百个并发用户的非常繁忙的系统中......
  • @marc_s 它是应用程序的本质。客户检查患者并对其进行一些分析并稍后保存。我不希望有人检查它并进行分析只是发现无法将结果保存回数据库,因为数据已被其他人更改,在应用程序中进行分析需要时间,这一切都将被浪费.这就是为什么我想绝对确定,如果有人签出病人可以独占访问它。我认为这不能使用乐观锁定来完成。

标签: c# sql-server database entity-framework stored-procedures


【解决方案1】:

老问题,所以你可能已经想通了,但我还是觉得有必要回答一下。对我来说,您正在尝试在数据存储级别执行应用程序级别的逻辑。我想我要做的就是在记录上放一个 CheckedOut 位标志。然后,当用户签出患者时,该标志设置为 true。应用程序将在允许其他用户检查之前检查以确保该标志为假。一旦原始用户重新检查了患者,该标志将连同任何更改一起设置回 false。

只是一个想法。

【讨论】:

  • 即使我们在这里只使用一个标志,当标志设置为 false 时两个用户可能会以某种方式请求患者并最终处于不良状态。
猜你喜欢
  • 2010-11-02
  • 2013-06-18
  • 2011-02-24
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多