我在Visual Studio中创建了一个WinForm,多个用户将访问它。 每当用户访问数据时,我想锁定数据,以便其他用户由于某些业务逻辑而无法同时查看相同的数据。
以下是我的c#代码
using (SqlConnection conn = new SqlConnection(connectString))
{
using (SqlCommand cmd=new SqlCommand("get_First_Unscan_Record_withUpdate",conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@usrName", username_Form);
conn.Open();
record_number = cmd.ExecuteScalar().ToString();
}
}
和我的SQL过程
CREATE PROCEDURE [dbo].[get_First_QC_Record_withUpdate]
@usrName nvarchar(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
Declare @srno int
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
select top 1 @srno=srno from [KYC].[dbo].[KYC_Index] (XLOCK) where [qc]='N' and [qc_int]='N' and transform_int='Y' and transform_status='Y' order by srno
update KYC_Index set [qc_int]='Y',[qc_int_by]=@usrName,[qc_int_time]=GETDATE(),@srno=KYC_Index.srno where srno = @srno
select @srno
我的用户仍然遇到死锁错误
{"事务(进程ID 72)在锁资源上与另一个进程死锁,并被选为死锁牺牲品。重新运行交易。"}
我做错了什么?或者我应该改变?请指导。
答案 0 :(得分:-2)
您无法通过锁定数据来隐藏数据。要隐藏其他用户,必须在同一个表中包含hidden
等列,或者在外部链接表中更好,例如hidden_rows
。 SERIALIZABLE
级别也不是必需的。您只需要BEGIN TRAN
/ COMMIT TRAN
或者您也可以从C#端执行相同操作(begin_tran - try {do_work,commit_tran} catch {rollback})。
https://msdn.microsoft.com/en-us/library/86773566(v=vs.110).aspx
在SELECT
语句中使用(UPDLOCK)
提示 - 它将锁定用于写入的行直到事务结束,并且对其他人可读。