【问题标题】:TranscationScope is not producing lock on sql table from different processTranscationScope 没有对来自不同进程的 sql 表产生锁定
【发布时间】:2016-03-02 09:12:34
【问题描述】:

第一个疑问:- 我们是否需要为 Select sql 语句创建 TranscationScope? 从我的 ASP.NET MVC 应用程序中,我尝试使用 TranscationalScope 将内容插入到一个表中。我在调用 ExecuteNonQuery() 之前在代码中设置了一个断点,并打开了一个 SQL Server Management Studio,并从表中执行了一个 select*;查询,但它没有等待并立即执行。 理想情况下,TranscationScope 曾经在桌子上加了锁,但我没有看到。

此外,我编写了一个控制台应用程序(而不是使用 SQL Server Management Studio)并使用 TranscationScope 执行了相同的选择查询,但它也立即执行而无需任何等待,并且我的断点在我的 ASP.NET Web 应用程序中仍然处于活动状态.

以下是我在 ASP.NET 应用程序中编写的代码。

public void UpdateBranchDetails()
    {
        try
        {
            using (TransactionScope ts = new TransactionScope())
            {
                SqlCommand cmd = new SqlCommand(@"UPDATE BranchDetails
                    SET 

              [Reviews] = " + Reviews.ToString() + @"
              ,[Overall_Satisfaction] = " + Overall_Satisfaction.ToString() + @"
              ,[Goods_Condition_At_Delivery] = " + Goods_Condition_At_Delivery.ToString() + @"
              ,[Staff_Behaviour] = " + Staff_Behaviour.ToString() + @"
              ,[Timeliness] = " + Timeliness.ToString() + @"
              ,[Packaging_And_Loading_Professionalism] = " + Packaging_And_Loading_Professionalism.ToString() + @"
              ,[Likelihood_To_Recommned] = " + Likelihood_To_Recommned.ToString() + @"

                WHERE BranchID = " + BranchID.ToString(), sqlConn);
                sqlConn.Open();
                cmd.ExecuteNonQuery();


                ts.Complete();
            }



        }
        catch (Exception ex)
        {

        }
        finally
        {
            sqlConn.Close();
        }
    }

上述代码中的sqlConn,是SqlConneciton类的对象,被声明为类成员。

【问题讨论】:

  • TransactionScope 不会直接在表上创建锁,它会创建一个事务(如果需要并且没有环境)。不确定您要达到的目标。

标签: c# sql asp.net asp.net-mvc-4 sql-server-2012


【解决方案1】:

我可以看到我的 select sql 查询正在等待事务完成。实际上,在我在行中插入内容的代码中,我没有执行 ExecuteNonQuery() 方法。我刚刚进入 transactionScope 并放置了断点。我的假设是,只需输入 TransactionScope,它就会锁定行以防止脏读。但这是错误的,理想情况下我们必须向 SQL 服务器发出 DML cmd,然后它才会锁定记录,直到我们提交事务...

【讨论】:

  • 在您执行某事之前,SQL Server 应该如何知道您将访问什么?
【解决方案2】:

首先要考虑的是,使用无参数构造函数创建新的TransactionScope 并不总是会创建数据库事务。如果调用代码已经创建了一个TransactionScope,它将使用那个(他们称之为环境事务)。

要考虑的第二件事是isolation level。这决定了数据库将允许的并发类型。

默认的isolation level 是ISOLATIONLEVEL_SERIALIZABLE。 这将锁定对已被并发事务读取的数据的任何写操作。

在您的示例中,您需要告诉数据库您需要对已读取的数据进行何种并发。

-- I require all access to the data I query in this transaction to be serialized
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION
SELECT * FROM [YourTable]

然后执行您的代码。您会注意到ExecuteNonQuery() 调用将停止,直到您在上面启动的事务中使用COMMIT 或ROLLBACK。

【讨论】:

  • 我尝试将构造函数更改为 TransactionScope ts = new TransactionScope(TransactionScopeOption.Required),默认情况下设置为 true。但我仍然看到选择 sql 查询正在通过 SQL Server 或我的控制台应用程序而无需等待
  • 要明确 TransactionScope 不会对表强制执行锁定。这完全取决于您设置的隔离。您是否在 SQL Management Studio 中的查询中设置隔离级别并开始事务?
  • 是的,我已将隔离级别设置为 SERIALIZABLE。但无济于事。我想要实现的是,当我从我的网站代码更新/插入表中的记录时,如果有人试图从同一个表中读取数据,那么他不应该最终读取脏数据。我想在同一张桌子上的读写之间进行某种同步。
  • 准确描述你到目前为止所做的,以及期望看到的。因为如果您在可序列化隔离模式下读取或写入记录,则来自不同线程的写入将等到完成
猜你喜欢
  • 1970-01-01
  • 2018-06-14
  • 2020-07-31
  • 2013-11-18
  • 2011-05-13
  • 2021-12-13
  • 2017-03-25
  • 1970-01-01
  • 2021-08-01
相关资源
最近更新 更多